Spring AOP has two proxying modes:
- "default" (JDK interface proxy if possible, fallback to CGLIB subclass proxy if not)
- when the target bean class implements one or more interfaces, a JDK dynamic proxy is created, intercepting calls _only_ to methods defined on the interface(s).
- when the target bean class does not implement any interfaces, a CGLIB subclass proxy is created, intercepting calls to _all_ class methods
- "forced-cglib"
- If _any_ of the elements (<tx:annotation-driven>, <aop:config>, <aop:aspectj-autoproxy>) present in the current ApplicationContext has a _proxy-target-class="true"_ attribute, CGLIB subclass proxies will be forced for _all_ advised beans. IDEA should look in the current fileset (but _not_ the parent fileset) to see if an element forcing proxy-target-class is present.
Observed behavior: IDEA seems to match all methods from the bean class.
It would be nice if the proxy type for a given bean was part of the AOP model: I think it can affect evaluation of
this() pointcut designator.
Issue was resolved
I'll create a separate issue for this() details.
public interface TargetInterface { void interfaceMethod(); } public class TargetClassNoInterface { public void classMethod() {} } public class TargetClassWithInterface implements TargetInterface { public void interfaceMethod() {} public void classMethod() {} }<!-- interface present, JDK interface proxy, should match "interfaceMethod" only --> <bean id="target" class="foo.bar.aop.testcase.TargetClassWithInterface"/> <aop:config> <aop:aspect ref="simpleAspectBean"> <aop:around method="before" pointcut="execution(* foo.bar.aop.testcase.*.*(..))"/> </aop:aspect> </aop:config><!-- no interfaces, CGLIB proxy, should match both methods --> <bean id="target" class="foo.bar.aop.testcase.TargetClassNoInterface"/> <aop:config> <aop:aspect ref="simpleAspectBean"> <aop:around method="before" pointcut="execution(* foo.bar.aop.testcase.*.*(..))"/> </aop:aspect> </aop:config><!-- no interfaces, CGLIB proxy (no other choice), should match both methods --> <bean id="target" class="foo.bar.aop.testcase.TargetClassNoInterface"/> <aop:config proxy-target-class="false"> <aop:aspect ref="simpleAspectBean"> <aop:around method="before" pointcut="execution(* foo.bar.aop.testcase.*.*(..))"/> </aop:aspect> </aop:config><!-- has interface, but forced CGLIB proxy, should match both methods --> <bean id="target" class="foo.bar.aop.testcase.TargetClassWithInterface"/> <aop:config proxy-target-class="true"> <aop:aspect ref="simpleAspectBean"> <aop:around method="before" pointcut="execution(* foo.bar.aop.testcase.*.*(..))"/> </aop:aspect> </aop:config><!-- has interface, but forced (by other element) CGLIB proxy, should match both methods --> <bean id="target" class="foo.bar.aop.testcase.TargetClassWithInterface"/> <tx:annotation-driven proxy-target-class="true"/> <aop:config> <aop:aspect ref="simpleAspectBean"> <aop:around method="before" pointcut="execution(* foo.bar.aop.testcase.*.*(..))"/> </aop:aspect> </aop:config><!-- has interface, but forced (by other element, "true" overrides "false") CGLIB proxy, should match both methods --> <bean id="target" class="foo.bar.aop.testcase.TargetClassWithInterface"/> <aop:aspectj-autoproxy proxy-target-class="true"/> <aop:config proxy-target-class="false"> <aop:aspect ref="simpleAspectBean"> <aop:around method="before" pointcut="execution(* foo.bar.aop.testcase.*.*(..))"/> </aop:aspect> </aop:config>