How springAop applies Advisor to methods

In the previous article https://blog.csdn.net/sinat_33472737/article/details/105414097 we learned how spring associates Advisor,

Part of the source code of wrapIfNecessary

// Create proxy if we have advice.
//Get the Advisor
Object related to the bean [] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {    this.advisedBeans.put(cacheKey, Boolean.TRUE);    Object proxy = createProxy(          bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));    this.proxyTypes.put(cacheKey, proxy.getClass());    return proxy; ) When and a certain When a bean has an associated Advisor, Spring will create a proxy object for the bean and store these related Advisors in the proxy object.






We take JdkDynamicAopProxy as an example to analyze how spring specifically determines which Advisor in a method needs to be executed. The bottom code of invoke in JdkDynamicAopProxy is to get the Advice in the Advisor related to the method, and it is the MethodInterceptor in spring.

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

This method will eventually call the getInterceptorsAndDynamicInterceptionAdvice method of org.springframework.aop.framework.DefaultAdvisorChainFactory

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
      Advised config, Method method, @Nullable Class<?> targetClass) {

   // This is somewhat tricky... We have to process introductions first,
   // but we need to preserve order in the ultimate list.
   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
   Advisor[] advisors = config.getAdvisors();
   List<Object> interceptorList = new ArrayList<>(advisors.length);
   Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
   Boolean hasIntroductions = null;

   for (Advisor advisor : advisors) {
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
            MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
            boolean match;
            if (mm instanceof IntroductionAwareMethodMatcher) {
               if (hasIntroductions == null) {
                  hasIntroductions = hasMatchingIntroductions (advisors, actualClass);
               }
               match = ((IntroductionAwareMethodMatcher) mm) .matches (method, actualClass, hasIntroductions);
            }
            else {
               match = mm.matches(method, actualClass);
            }
            if (match) {
               MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
               if (mm.isRuntime()) {
                  // Creating a new object instance in the getInterceptors() method
                  // isn't a problem as we normally cache created chains.
                  for (MethodInterceptor interceptor : interceptors) {
                     interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                  }
               }
               else {
                  interceptorList.addAll(Arrays.asList(interceptors));
               }
            }
         }
      }
      else if (advisor instanceof IntroductionAdvisor) {
         IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
         if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
         }
      }
      else {
         Interceptor[] interceptors = registry.getInterceptors(advisor);
         interceptorList.addAll(Arrays.asList(interceptors));
      }
   }

   return interceptorList;
}

The principle is also to match the ClassFilter and MethodMatcher of pointcut. If the matching result is true, call the getInterceptors method of org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry and wrap it into MethodInterceptor to return

 

Guess you like

Origin blog.csdn.net/sinat_33472737/article/details/105436558