springAop原理之Advisor接口族介绍及通过spring事务注解@Transactional关联的Advisor分析源码中是如何将Advisor和bean关联起来的

一、接口概述

 Advisor:包含AOP通知的基本接口(在连接点采取的操作)和一个确定建议的适用性的过滤器(例如一个切入点)。这个接口不是供Spring用户使用的,而是允许在支持不同类型的通知时具有通用性。Spring AOP基于通过方法拦截的环绕通知传递,符合AOP联盟拦截API。Advisor接口支持不同类型的建议,如之前和之后的通知,不需要使用拦截实现。

PointcutAdvisor:由切入点驱动的所有Advisor的超级接口。这几乎涵盖了除introduction advisors以外的所有Advisor。PointcutAdvisor中包含了一个Pointcut成员变量,也就是切点,在加上Advisor接口中的Advice,就形成了一个完整的切面。

StaticMethodMatcherPointcutAdvisor:静态方法匹配器切点定义的切面,默认情况下匹配所有的的目标类。(shiro权限设计就是通过继承该类实现的)。

InstantiationModelAwarePointcutAdvisor:该接口有唯一实现类InstantiationModelAwarePointcutAdvisorImpl。该类就是我们通常在项目中通过aspectj注解实现的切面被包装后的Advisor。

AspectJExpressionPointcutAdvisor:用于AspectJ切点表达式定义切点的切面

AbstractPointcutAdvisor:PointcutAdvisor实现的抽象基类,可以为返回特定切入点/通知或可自由配置的切入点/通知的子类

二、spring如何判断bean是否需要被代理

spring在创建完bean后,需要判断是否需要给当前bean创建代理对象。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类中的doCreateBean方法后会调用applyBeanPostProcessorsAfterInitialization方法,该方法会调用所有BeanPostProcessor的postProcessAfterInitialization。org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator就是一个BeanPostProcessor,该类的postProcessAfterInitialization会调用wrapIfNecessary方法,即该bean是否需要被包装成代理对象。是否需要代理原则就是该bean有没有与之相关的Advisor,有就代理。

三、spring如何查找所有Advisor源码及如何判断某个bean与之关联的Advisor有哪些

wrapIfNecessary部分源码

// Create proxy if we have advice.
//获取bean有关的Advisor
Object[] 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;
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  //查找所有的Advisor
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
  //查找所有的Advisor中可应用的某个bean的Advisor
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

findCandidateAdvisors()源码简单可总结为:从容器中获取所有实现了Advisor的类,在加上aspectJ创建的Advisor。

记下来我们看下findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)源码

protected List<Advisor> findAdvisorsThatCanApply(
      List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
   //在ThreadLocal中标记当前beanName
   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
     //在ThreadLocal中移除当前beanName
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

AopUtils findAdvisorsThatCanApply源码分析

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List<Advisor> eligibleAdvisors = new ArrayList<>();
   for (Advisor candidate : candidateAdvisors) {
      //是否为引入切面并且是否能被应用到
      if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
         eligibleAdvisors.add(candidate);
      }
   }
   //目前用不到,所以值为false
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         // already processed
         continue;
      }
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}

以BeanFactoryTransactionAttributeSourceAdvisor(事务注解关联的Advisor)为例,分析下面源码。BeanFactoryTransactionAttributeSourceAdvisor的切点为TransactionAttributeSourcePointcut,TransactionAttributeSourcePointcut 继承了StaticMethodMatcherPointcut,StaticMethodMatcherPointcut对应的ClassFilter为TrueClassFilter,所以1处会匹配任意类。

StaticMethodMatcherPointcut继承StaticMethodMatcher,所以TransactionAttributeSourcePointcut的MethodMatcher 为TransactionAttributeSourcePointcut自身。所以2处执行的就是TransactionAttributeSourcePointcut的matches(Method method, Class<?> targetClass)方法

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
   Assert.notNull(pc, "Pointcut must not be null");  
   //1
  if (!pc.getClassFilter().matches(targetClass)) {
      return false;
   }

   MethodMatcher methodMatcher = pc.getMethodMatcher();
   if (methodMatcher == MethodMatcher.TRUE) {
      // No need to iterate the methods if we're matching any method anyway...
      return true;
   }

   IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
   if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
      introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
   }
  //查找当前类及其祖宗类实现的所有接口
   Set<Class<?>> classes = new LinkedHashSet<>();
   if (!Proxy.isProxyClass(targetClass)) {
      classes.add(ClassUtils.getUserClass(targetClass));
   }
   classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

   for (Class<?> clazz : classes) {
      //获取方法列表包含从父类继承的的方法
      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
      for (Method method : methods) {
        //2
         if (introductionAwareMethodMatcher != null ?
               introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
               methodMatcher.matches(method, targetClass)) {
            return true;
         }
      }
   }

   return false;
}

TransactionAttributeSourcePointcut的matches(Method method, Class<?> targetClass)源码:

@Override
public boolean matches(Method method, Class<?> targetClass) {
   if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
         PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
         PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
      return false;
   }
   TransactionAttributeSource tas = getTransactionAttributeSource();
   return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

先判断TransactionalProxy、PlatformTransactionManager、PersistenceExceptionTranslator是否为当前class的父类,是的话返回false。我们发现TransactionAttributeSourcePointcut其实是个抽象类,而TransactionAttributeSourcePointcut中的getTransactionAttributeSource也是一个抽象方法。从BeanFactoryTransactionAttributeSourceAdvisor源码,我们可以看到,BeanFactoryTransactionAttributeSourceAdvisor定义TransactionAttributeSourcePointcut时,已经重写了该方法

private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
   @Override
   @Nullable
   protected TransactionAttributeSource getTransactionAttributeSource() {
      return transactionAttributeSource;
   }
};

返回的TransactionAttributeSource是BeanFactoryTransactionAttributeSourceAdvisor的一个成员变量。而BeanFactoryTransactionAttributeSourceAdvisor是spring通过@bean配置的(ProxyTransactionManagementConfiguration的transactionAdvisor()方法)

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
   BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
   advisor.setTransactionAttributeSource(transactionAttributeSource());
   advisor.setAdvice(transactionInterceptor());
   if (this.enableTx != null) {
      advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
   }
   return advisor;
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
   return new AnnotationTransactionAttributeSource();
}

所以最终的TransactionAttributeSource为AnnotationTransactionAttributeSource。AnnotationTransactionAttributeSource调用getTransactionAttribute(method, targetClass)实际上是调用父类AbstractFallbackTransactionAttributeSource中的方法

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
   if (method.getDeclaringClass() == Object.class) {
      return null;
   }

   // First, see if we have a cached value.
   Object cacheKey = getCacheKey(method, targetClass);
   TransactionAttribute cached = this.attributeCache.get(cacheKey);
   if (cached != null) {
      // Value will either be canonical value indicating there is no transaction attribute,
      // or an actual transaction attribute.
      if (cached == NULL_TRANSACTION_ATTRIBUTE) {
         return null;
      }
      else {
         return cached;
      }
   }
   else {
      // We need to work it out.
      TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
      // Put it in the cache.
      if (txAttr == null) {
         this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
      }
      else {
         String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
         if (txAttr instanceof DefaultTransactionAttribute) {
            ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
         }
         if (logger.isTraceEnabled()) {
            logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
         }
         this.attributeCache.put(cacheKey, txAttr);
      }
      return txAttr;
   }
}

computeTransactionAttribute(method, targetClass)继续向下就会调用AnnotationTransactionAttributeSource中findTransactionAttribute(Method method)、findTransactionAttribute(Class<?> clazz),查找方法或类上是否有Transactional注解。

猜你喜欢

转载自blog.csdn.net/sinat_33472737/article/details/105414097