AOP源码解析之二-创建AOP代理前传,获取AOP信息

博客 分享
0 116
张三
张三 2022-03-21 14:57:00
悬赏:0 积分 收藏

AOP源码解析之二-创建AOP代理前传,获取AOP信息

AOP源码解析之二-创建AOP代理前传,获取AOP信息。

上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中。

本篇文章重点对前半部分,如何获取到AOP信息的过程解读。

在Spring的核心方法Refresh方法中,aop是在

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

开始切入的,该文章就开始深入这个方法进行解析。

@Nullable	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {		Object bean = null;		// 检测是否被解析过		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {			// Make sure bean class is actually resolved at this point.			// hasInstantiationAwareBeanPostProcessors()是来判断容器中是否有InstantiationAwareBeanPostProcessor的实现bean			// AOP切面后置处理器AspectJAwareAdvisorAutoProxyCreator就实现了InstantiationAwareBeanPostProcessor接口			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {				Class<?> targetType = determineTargetType(beanName, mbd);				if (targetType != null) {					// 执行实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor中的前置处理方法postProcessBeforeInstantiation方法					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);					if (bean != null) {						// 执行实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor中的后置处理方法postProcessAfterInitialization方法						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);					}				}			}			mbd.beforeInstantiationResolved = (bean != null);		}		return bean;	}

见名知意,resolveBeforeInstantiation(执行初始化前方法),这一步主要判断一下工厂中是否有 InstantiationAwareBeanPostProcessor 的实现bean。InstantiationAwareBeanPostProcessor 应该是AOP最核心的接口了。

我们看一下InstantiationAwareBeanPostProcessor 的继承结构。

image-20220321090152628

我们详细的说下InstantiationAwareBeanPostProcessor 这个接口。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {   Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;   boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;   PropertyValues postProcessPropertyValues(         PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;}

它和 BeanPostProcessor 的方法非常相似,而且它还继承了 BeanPostProcessor。

下面是 BeanPostProcessor 中的两个方法:

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

发现没有,InstantiationAwareBeanPostProcessor 是 Instantiation,BeanPostProcessor 是 Initialization,它代表的是 bean 在实例化完成并且属性注入完成,在执行 init-method 的前后进行作用的。

而 InstantiationAwareBeanPostProcessor 的执行时机要前面一些,我们回到refresh方法的doCreateBean中看一下。

image-20220321091420346

看到这读者想必对于aop的执行时机已经模模糊糊的心里有个大概了。

我们定义的环绕通知,创建代理一定是在postProcessBeforeInitialization完成的。

我们的重点就是看看postProcessBeforeInitialization的方法中的通知怎么获取,怎么创建代理对象的进行详细的解读。

本文先对前半部分解读。

我们继续看postProcessBeforeInitialization有哪些实现类。

image-20220321092132443

我们重点看AbstractAutoProxyCreator的实现类。

@Override	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {		if (bean != null) {			Object cacheKey = getCacheKey(bean.getClass(), beanName);			// 1.判断当前bean是否需要被代理,如果需要则进行封装			if (this.earlyProxyReferences.remove(cacheKey) != bean) {				//1.判断当前bean是否需要被代理,如果需要则进行封装				return wrapIfNecessary(bean, beanName, cacheKey);			}		}		return bean;	}

如果需要代理执行继wrapIfNecessary方法。

//这个方法将返回代理类	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {		// 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {			return bean;		}		// 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {			return bean;		}		// 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {			this.advisedBeans.put(cacheKey, Boolean.FALSE);			return bean;		}		// Create proxy if we have advice.		// 4.获取当前bean的Advices和Advisors		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);		// 5.如果存在增强器则创建代理		if (specificInterceptors != DO_NOT_PROXY) {			this.advisedBeans.put(cacheKey, Boolean.TRUE);			// 创建代理...创建代理...创建代理...			// 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),			// 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))			Object proxy = createProxy(					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));			// 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存			this.proxyTypes.put(cacheKey, proxy.getClass());			return proxy;		}		// 6.标记为无需处理		this.advisedBeans.put(cacheKey, Boolean.FALSE);		return bean;	}

4.1 我们先查看第一条主线,获取当前bean的Advices和Advisors

@Override	@Nullable	protected Object[] getAdvicesAndAdvisorsForBean(			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {		// 1.找到符合条件的Advisor		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);		if (advisors.isEmpty()) {			// 2.如果没有符合条件的Advisor,则返回null			return DO_NOT_PROXY;		}		return advisors.toArray();	}

注:Advisors即是aop的环绕通知。

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {		// 1.查找所有的候选Advisor		List<Advisor> candidateAdvisors = findCandidateAdvisors();		// 2.从所有候选的Advisor中找出符合条件的		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);		// 3.扩展方法,留个子类实现		extendAdvisors(eligibleAdvisors);		if (!eligibleAdvisors.isEmpty()) {			// 4.对符合条件的Advisor进行排序			eligibleAdvisors = sortAdvisors(eligibleAdvisors);		}		return eligibleAdvisors;	}

这一步所做的事很简单,就是查找所有候选的Advisor,但是调用链路特别的长,如果将这些彻底搞明白,还是需要耗费一番功夫的,读者可以选择深入程度。

1、寻找可用的Advisor

public List<Advisor> findAdvisorBeans() {		// Determine list of advisor bean names, if not cached already.		// 1.确认advisor的beanName列表,优先从缓存中拿		String[] advisorNames = this.cachedAdvisorBeanNames;		if (advisorNames == null) {			// Do not initialize FactoryBeans here: We need to leave all regular beans			// uninitialized to let the auto-proxy creator apply to them!			//  1.1 如果缓存为空,则获取class类型为Advisor的所有bean名称			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(					this.beanFactory, Advisor.class, true, false);			this.cachedAdvisorBeanNames = advisorNames;		}		if (advisorNames.length == 0) {			return new ArrayList<>();		}		// 2.遍历处理advisorNames		List<Advisor> advisors = new ArrayList<>();		for (String name : advisorNames) {			if (isEligibleBean(name)) {				// 2.1 跳过当前正在创建的advisor				if (this.beanFactory.isCurrentlyInCreation(name)) {					if (logger.isTraceEnabled()) {						logger.trace("Skipping currently created advisor '" + name + "'");					}				}				else {					try {						// 2.2 通过beanName获取对应的bean对象,并添加到advisors						advisors.add(this.beanFactory.getBean(name, Advisor.class));					}					catch (BeanCreationException ex) {						Throwable rootCause = ex.getMostSpecificCause();						if (rootCause instanceof BeanCurrentlyInCreationException) {							BeanCreationException bce = (BeanCreationException) rootCause;							String bceBeanName = bce.getBeanName();							if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {								if (logger.isTraceEnabled()) {									logger.trace("Skipping advisor '" + name +											"' with dependency on currently created bean: " + ex.getMessage());								}								// Ignore: indicates a reference back to the bean we're trying to advise.								// We want to find advisors other than the currently created bean itself.								continue;							}						}						throw ex;					}				}			}		}		// 3.返回符合条件的advisor列表		return advisors;	}
/** * 找到符合条件的Advisor * @return */@Overrideprotected List<Advisor> findCandidateAdvisors() {   // Add all the Spring advisors found according to superclass rules.   List<Advisor> advisors = super.findCandidateAdvisors();   // Build Advisors for all AspectJ aspects in the bean factory.   if (this.aspectJAdvisorsBuilder != null) {      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());   }   return advisors;}
public List<Advisor> buildAspectJAdvisors() {   List<String> aspectNames = this.aspectBeanNames;   // 1.如果aspectNames为空,则进行解析   if (aspectNames == null) {      synchronized (this) {         aspectNames = this.aspectBeanNames;         if (aspectNames == null) {            List<Advisor> advisors = new ArrayList<>();            aspectNames = new ArrayList<>();            // 1.1 获取所有的beanName            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(                  this.beanFactory, Object.class, true, false);            // 1.2 循环遍历所有的beanName,找出对应的增强方法            for (String beanName : beanNames) {               // 1.3 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator               // 实现了自己的逻辑,支持使用includePatterns进行筛选               if (!isEligibleBean(beanName)) {                  continue;               }               // We must be careful not to instantiate beans eagerly as in this case they               // would be cached by the Spring container but would not have been weaved.               // 获取beanName对应的bean的类型               Class<?> beanType = this.beanFactory.getType(beanName);               if (beanType == null) {                  continue;               }               // 1.4 如果beanType存在Aspect注解则进行处理               if (this.advisorFactory.isAspect(beanType)) {                  // 将存在Aspect注解的beanName添加到aspectNames列表                  aspectNames.add(beanName);                  // 新建切面元数据                  AspectMetadata amd = new AspectMetadata(beanType, beanName);                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {                     // 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例                     MetadataAwareAspectInstanceFactory factory =                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);                     // 1.5 解析标记AspectJ注解中的增强方法*********************                     List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);                     // 1.6 放到缓存中                     if (this.beanFactory.isSingleton(beanName)) {                        // 如果beanName是单例则直接将解析的增强方法放到缓存                        this.advisorsCache.put(beanName, classAdvisors);                     }                     else {                        // 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法                        this.aspectFactoryCache.put(beanName, factory);                     }                     // 1.7 将解析的增强器添加到advisors                     advisors.addAll(classAdvisors);                  }                  else {                     // Per target or per this.                     if (this.beanFactory.isSingleton(beanName)) {                        // 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常                        throw new IllegalArgumentException("Bean with name '" + beanName +                              "' is a singleton, but aspect instantiation model is not singleton");                     }                     MetadataAwareAspectInstanceFactory factory =                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);                     // 将factory放到缓存,之后可以通过factory来解析增强方法                     this.aspectFactoryCache.put(beanName, factory);                     // 解析标记AspectJ注解中的增强方法,并添加到advisors中                     advisors.addAll(this.advisorFactory.getAdvisors(factory));                  }               }            }            // 1.9 将解析出来的切面beanName放到缓存aspectBeanNames            this.aspectBeanNames = aspectNames;            return advisors;         }      }   }   if (aspectNames.isEmpty()) {      return Collections.emptyList();   }   List<Advisor> advisors = new ArrayList<>();   for (String aspectName : aspectNames) {      List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);      if (cachedAdvisors != null) {         advisors.addAll(cachedAdvisors);      }      else {         MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);         advisors.addAll(this.advisorFactory.getAdvisors(factory));      }   }   // 1.10 最后返回解析出来的增强器   return advisors;}
@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {   // 1.前面我们将beanClass和beanName封装成了aspectInstanceFactory的AspectMetadata属性,   // 这边可以通过AspectMetadata属性重新获取到当前处理的切面类   Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();   // 2.获取当前处理的切面类的名字   String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();   // 3.校验切面类   validate(aspectClass);   // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator   // so that it will only instantiate once.   // 4.使用装饰器包装MetadataAwareAspectInstanceFactory,以便它只实例化一次。   MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);   List<Advisor> advisors = new ArrayList<>();   // 5.获取切面类中的方法(也就是我们用来进行逻辑增强的方法,被@Around、@After等注解修饰的方法,使用@Pointcut的方法不处理)   for (Method method : getAdvisorMethods(aspectClass)) {      // 6.处理method,获取增强器      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);      if (advisor != null) {         // 7.如果增强器不为空,则添加到advisors         advisors.add(advisor);      }   }   // If it's a per target aspect, emit the dummy instantiating aspect.   if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {      // 8.如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)      Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);      advisors.add(0, instantiationAdvisor);   }   // Find introduction fields.   // 9.获取DeclareParents注解   for (Field field : aspectClass.getDeclaredFields()) {      Advisor advisor = getDeclareParentsAdvisor(field);      if (advisor != null) {         advisors.add(advisor);      }   }   return advisors;}
@Override@Nullablepublic Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,      int declarationOrderInAspect, String aspectName) {   // 1.校验切面类   validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());   // 2.AspectJ切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,   // 如:@Around("execution(* com.joonwhee.open.aop.*.*(..))")   AspectJExpressionPointcut expressionPointcut = getPointcut(         candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());   // 3.如果expressionPointcut为null,则直接返回null   if (expressionPointcut == null) {      return null;   }   // 4.根据切点信息生成增强器   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}

获取到@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut定义注解信息

@Nullableprivate AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {   // 1.查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)   // 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解   AspectJAnnotation<?> aspectJAnnotation =         AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);   // 2.如果方法没有使用AspectJ的注解,则返回null   if (aspectJAnnotation == null) {      return null;   }   // 3.使用AspectJExpressionPointcut实例封装获取的信息   AspectJExpressionPointcut ajexp =         new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);   // 提取得到的注解中的表达式,   // 例如:@Around("execution(* com.joonwhee.open.aop.*.*(..))"),得到:execution(* com.joonwhee.open.aop.*.*(..))   ajexp.setExpression(aspectJAnnotation.getPointcutExpression());   if (this.beanFactory != null) {      ajexp.setBeanFactory(this.beanFactory);   }   return ajexp;}
@Nullableprotected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {   // 设置要查找的注解类   for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {      // 查找方法上是否存在当前遍历的注解,如果有则返回      AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);      if (foundAnnotation != null) {         return foundAnnotation;      }   }   return null;}

2、获取切点以后就需要生成增强器了。

 new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,				this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
/** * 根据切点信息生成增强器 * @param declaredPointcut * @param aspectJAdviceMethod * @param aspectJAdvisorFactory * @param aspectInstanceFactory * @param declarationOrder * @param aspectName */public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,      Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,      MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {   // 1.简单的将信息封装在类的实例中   this.declaredPointcut = declaredPointcut;   this.declaringClass = aspectJAdviceMethod.getDeclaringClass();   this.methodName = aspectJAdviceMethod.getName();   this.parameterTypes = aspectJAdviceMethod.getParameterTypes();   // aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)   this.aspectJAdviceMethod = aspectJAdviceMethod;   this.aspectJAdvisorFactory = aspectJAdvisorFactory;   this.aspectInstanceFactory = aspectInstanceFactory;   this.declarationOrder = declarationOrder;   this.aspectName = aspectName;   // 2.是否需要延迟实例化   if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {      // Static part of the pointcut is a lazy type.      Pointcut preInstantiationPointcut = Pointcuts.union(            aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);      // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.      // If it's not a dynamic pointcut, it may be optimized out      // by the Spring AOP infrastructure after the first evaluation.      this.pointcut = new PerTargetInstantiationModelPointcut(            this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);      this.lazy = true;   }   else {      // A singleton aspect.      this.pointcut = this.declaredPointcut;      this.lazy = false;      // 3.实例化增强器:根据注解中的信息初始化对应的增强器      this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);   }}

经过以上长长的源码分析过程,就将aop的第一个大过程,获取到我们定义的@Before、@After的方法以后,进行增强,下一步就要拿到这些获取的信息去创建代理对象了。

posted @ 2022-03-21 14:43 程序员田同学 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员