Reputation: 1546
I'm trying to understand Spring proxy mechanism and I have problem with one thing. I have Interface:
public interface MyInterface{
void myMethod();
}
and implementing class:
@Component
public class MyBean implements MyInterface{
@Override
public void myMethod(){
//do something
}
}
Now I create Aspect, for example:
@Aspect
@Component
public class LogAspect {
@Before("execution(public * *(..))")
public void logBefore() {
System.out.println("Before aspect");
}
}
And I have simple starter 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();
}
}
According to the Spring docs we can read:
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.
But I got an error No qualifying bean of type [MyBean] is defined. It works only when I enable CGLib proxying by @EnableAspectJAutoProxy(proxyTargetClass = true)
.
Can someone explain what I am missing here? Why MyBean is not discovered when using AOP? ctx.getBean(MyInterface.class)
works, but I can't imagine the situation with many implementations of such interface.
Upvotes: 0
Views: 3423
Reputation: 1
Because if you check up your bean class you'll find com.sun.proxy.$Proxy21 (or something similar) instead, which wraps your method. They are incompatible types even they have the same interface. For example:
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");
}
}
So when you call
public static void main(String[] args) {
Bb b = new Bb();
Cc c=b; // Error
AnInterface c=b; // Ok
}
Upvotes: 0
Reputation: 9516
The target object to be proxied (MyBean) implements at least one interface (MyInterface), so a JDK proxy is used. This proxy implements MyInterface, but is NOT an instance of MyBean. Thats why
MyInterface bean = ctx.getBean(MyInterface.class);
works and
MyBean bean = ctx.getBean(MyBean.class);
not.
CGLib proxies are created by subclassing the target object, so the bean created is a subclass of MyBean and implements MyInterface. In this case also
MyBean bean = ctx.getBean(MyBean.class);
works.
...but I can't imagine the situation with many implementations of such interface.
The only reason for MyInterface could be, to allow spring to create a JDK proxy, so there is no need to have many implementations.
Upvotes: 3