After bean initialization, execute abstractautoproxycreator post processor. You will get the advisor adapted to the bean. Here, the [pc.getclassfilter(). Matches (targetclass)] method is executed, including the verification of the method. However, when executing the proxy class method, you get the advisor of the bean and verify it again. Why do you need to check twice?? 😊
Comment From: sbrannen
Can you be more explicit about your expectations?
Are you saying that org.springframework.aop.support.AopUtils.canApply(Pointcut, Class<?>, boolean)
gets invoked multiple times and that it should only be invoked once?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: JavaFenSi
I may know what he is talking about, because I had the same question before, and I figured it out myself. He means when you execute AbstractAutoProxyCreator->postProcessAfterInitialization->wrapIfNecessary, you wrap a bean for proxy. Then you execute wrapIfNecessary->getAdvicesAndAdvisorsForBean->findEligibleAdvisors->findAdvisorsThatCanApply->canApply, in that function you have code below:
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
That means if the pointcut expression in Advisor matches one method in targetClass, return true. After this you get all Advisors that matches this targetClass.
And then when you finish creating the proxy bean, you what to execute the method in that bean. When you do that, you will come to CglibAopProxy#DynamicAdvisedInterceptor->intercept->(CglibAopProxy#CglibMethodInvocation).proceed()->(ReflectiveMethodInvocation).proceed(), and you have code below:
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
He means you check it twice, see if the pointcut expression in Advisor matches this method.
Actually, they are different. The first match is used to filter the Advisors, only the Advisor whose pointcut expression matches the method will be retained. Note that as long as there is one method that matches the pointcut expression, it will return true, the other methods will be ignored. But when you actually execute method in proxy bean, you don't know whether this method actually matches the pointcut expression in Advisor.
For example: Here I have a target class:
public class MyCalculator{
public Integer add(Integer i, Integer j) throws NoSuchMethodException {
Integer result = i+j;
return result;
}
public Integer sub(Integer i, Integer j) throws NoSuchMethodException {
Integer result = i-j;
return result;
}
public Integer mul(Integer i, Integer j) throws NoSuchMethodException {
Integer result = i*j;
return result;
}
public Integer div(Integer i, Integer j) throws NoSuchMethodException {
Integer result = i/j;
return result;
}
public Integer show(Integer i){
System.out.println("show .....");
return i;
}
}
Here is xml:
<aop:before method="start" pointcut-ref="point1"></aop:before>
<aop:after method="logFinally" pointcut-ref="point2"></aop:after>
</aop:aspect>
</aop:config>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
When you execute wrapIfNecessary, you will have all two Advisors in collection, because at least one method matches their expressions. But when you execute "sub" or "div" in MyCalculator, you don't have to enhance them, because they don't match these two Advisors. Only thing you have to do is to enhance "add" and "mul" in MyCalculator, that is why the second "match" exists.
Am I right?
Comment From: snicoll
This is similar to #27627, I am afraid the issue tracker is not a place to have a discussion like this. If you're trying to report an actual problem, that should be done in the form of a small sample that we can run ourselves. Thanks!