Spring AOP代理和接口实现
Spring AOP proxy and interface implementation
我正在尝试了解 Spring 代理机制,但我遇到了一件事。
我有接口:
public interface MyInterface{
void myMethod();
}
并实施 class:
@Component
public class MyBean implements MyInterface{
@Override
public void myMethod(){
//do something
}
}
现在我创建Aspect,例如:
@Aspect
@Component
public class LogAspect {
@Before("execution(public * *(..))")
public void logBefore() {
System.out.println("Before aspect");
}
}
我有简单的启动器class:
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class SpringAopApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
SpringAopApplication.class);
MyBean bean = ctx.getBean(MyBean.class);
// MyInterface bean = ctx.getBean(MyInterface.class); //works
bean.myMethod();
ctx.close();
}
}
根据 Spring 文档,我们可以阅读:
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
但是我得到一个错误没有定义 [MyBean] 类型的合格 bean。只有当我通过 @EnableAspectJAutoProxy(proxyTargetClass = true)
启用 CGLib 代理时它才有效。
有人可以解释我在这里缺少什么吗?为什么在使用 AOP 时没有发现 MyBean? ctx.getBean(MyInterface.class)
可以,但我无法想象这种接口有很多实现的情况。
被代理的目标对象(MyBean)至少实现了一个接口(MyInterface),所以使用了JDK代理。
此代理实现 MyInterface,但不是 MyBean 的实例。
这就是为什么
MyInterface bean = ctx.getBean(MyInterface.class);
有效并且
MyBean bean = ctx.getBean(MyBean.class);
没有。
CGLib 代理是通过子类化目标对象创建的,因此创建的 bean 是 MyBean 的子类并实现了 MyInterface。
在这种情况下也
MyBean bean = ctx.getBean(MyBean.class);
有效。
...but I can't imagine the situation with many implementations of such interface.
MyInterface 的唯一原因可能是允许 spring 创建一个 JDK 代理,因此不需要有很多实现。
因为如果您检查 bean class,您会发现 com.sun.proxy.$Proxy21(或类似的东西),它包装了您的方法。它们是不兼容的类型,即使它们具有相同的接口。
例如:
public interface AnInterface {
void func();
}
public class Bb implements AnInterface{
@Override
public void func() {
System.out.println("bb");
}
}
public class Cc implements AnInterface{
@Override
public void func() {
System.out.println("cc");
}
}
所以当你打电话给
public static void main(String[] args) {
Bb b = new Bb();
Cc c=b; // Error
AnInterface c=b; // Ok
}
我正在尝试了解 Spring 代理机制,但我遇到了一件事。 我有接口:
public interface MyInterface{
void myMethod();
}
并实施 class:
@Component
public class MyBean implements MyInterface{
@Override
public void myMethod(){
//do something
}
}
现在我创建Aspect,例如:
@Aspect
@Component
public class LogAspect {
@Before("execution(public * *(..))")
public void logBefore() {
System.out.println("Before aspect");
}
}
我有简单的启动器class:
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class SpringAopApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
SpringAopApplication.class);
MyBean bean = ctx.getBean(MyBean.class);
// MyInterface bean = ctx.getBean(MyInterface.class); //works
bean.myMethod();
ctx.close();
}
}
根据 Spring 文档,我们可以阅读:
If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.
但是我得到一个错误没有定义 [MyBean] 类型的合格 bean。只有当我通过 @EnableAspectJAutoProxy(proxyTargetClass = true)
启用 CGLib 代理时它才有效。
有人可以解释我在这里缺少什么吗?为什么在使用 AOP 时没有发现 MyBean? ctx.getBean(MyInterface.class)
可以,但我无法想象这种接口有很多实现的情况。
被代理的目标对象(MyBean)至少实现了一个接口(MyInterface),所以使用了JDK代理。 此代理实现 MyInterface,但不是 MyBean 的实例。 这就是为什么
MyInterface bean = ctx.getBean(MyInterface.class);
有效并且
MyBean bean = ctx.getBean(MyBean.class);
没有。
CGLib 代理是通过子类化目标对象创建的,因此创建的 bean 是 MyBean 的子类并实现了 MyInterface。 在这种情况下也
MyBean bean = ctx.getBean(MyBean.class);
有效。
...but I can't imagine the situation with many implementations of such interface.
MyInterface 的唯一原因可能是允许 spring 创建一个 JDK 代理,因此不需要有很多实现。
因为如果您检查 bean class,您会发现 com.sun.proxy.$Proxy21(或类似的东西),它包装了您的方法。它们是不兼容的类型,即使它们具有相同的接口。 例如:
public interface AnInterface {
void func();
}
public class Bb implements AnInterface{
@Override
public void func() {
System.out.println("bb");
}
}
public class Cc implements AnInterface{
@Override
public void func() {
System.out.println("cc");
}
}
所以当你打电话给
public static void main(String[] args) {
Bb b = new Bb();
Cc c=b; // Error
AnInterface c=b; // Ok
}