【十一】Spring源码分析之AOP----AnnotationAwareAspectJAutoProxyCreator扫描@Aspect,创建Advisor

一、简介:

AOP源码分析主要分为5个篇章:上一篇讲了注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator。

1. 注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator。

【十】Spring源码分析之AOP----注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator
2. 扫描容器中的切面,创建Advisor对象。就是本篇。

3. 目标bean和每个Advisor匹配,找出该bean在被代理的时候需要用到哪些Advisor

【十二】Spring源码分析之AOP----匹配出作用于被代理类Advisor

4. 创建代理对象

【十三】Spring源码分析之AOP----生成代理对象

5. 被代理类的方法一次调用流程。

【十四】Spring源码分析之AOP----JdkDynamicAopProxy代理对象invoke调用

本篇主要是讲AnnotationAwareAspectJAutoProxyCreator类中的两个方法:

postProcessBeforeInstantiation(扫描容器中的切面@Aspect,解析创建Advisor对象) 和postProcessAfterInitialization。

而真正创建代理类的的详解下一篇再讲。

继承关系图:

可以看到AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator,AbstractAutoProxyCreator又实现了BeanPostProcessorInstantiationAwareBeanPostProcessor接口。

所以AnnotationAwareAspectJAutoProxyCreator中(其实在父类AbstractAutoProxyCreator中)有这几个方法在创建bean的时候会调用:

后置处理方法名称何时调用该方法该方法执行逻辑
postProcessBeforeInstantiation  在Bean实例化之前调用

1.解析出@Aspect注解的类中的Advisor(advice增强方法处理逻辑+该方法切入点pointcut)

2.如果Bean设置了自定义TargetSource就在该方法中生成代理

postProcessAfterInstantiation在Bean实例化之后调用该方法无逻辑操作
postProcessBeforeInitialization  在Bean初始化前调用该方法无逻辑操作
postProcessAfterInitialization 在Bean初始化后调用如果Bean没有设置自定义TargetSource就在该方法中生成代理

二、postProcessBeforeInstantiation

AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor,在每一个bean实例化之前,会调用它的postProcessBeforeInstantiation,而他自己没有该方法,所以是调用他父类AbstractAutoProxyCreator类的postProcessBeforeInstantiation方法处理需要代理的bean。

方法调用栈:

源码:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {

        // 1.是工厂bean则在beanName前面加上&符号
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {

            // 当前bean是否保存在advisedBeans(保存所有需要被增强的bean)中,这是一个缓存
			if (this.advisedBeans.containsKey(cacheKey)) {
                // 存在就直接返回
				return null;
			}

            // 该bean是不是一个永远不需要被代理的基础设施Bean,是否实现接口:Advice、Pointcut、Advisor、AopInfrastructureBean,是不是有@Aspect注解,是不是实现了Advisor,如果是则加入到AnnotationAwareAspectJAutoProxyCreator的advisedBeans中,表示需要被增强。
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.

        // 如果BeanName不为空,且有自定义的targetSource,则在这里创建代理对象
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}

		return null;
	}

 做了3件事:

1.是工厂bean则在beanName前面加上&符号

2.该bean是不是基础类,是否实现接口:Advice、Pointcut、Advisor、AopInfrastructureBean,是不是有@Aspect注解,是不是实现了Advisor,如果是则加入到AnnotationAwareAspectJAutoProxyCreator的advisedBeans中,表示需要被增强。

3.如果BeanName不为空,且有自定义的targetSource,则在这里创建代理对象。调用getAdvicesAndAdvisorsForBean方法得到advices和Advisors,调用createProxy方法创建代理对象。调用的这两个方法会专门写一篇创建代理对象的博客来介绍。

2.1 isInfrastructureClass方法

AnnotationAwareAspectJAutoProxyCreator类的isInfrastructureClass方法

	protected boolean isInfrastructureClass(Class<?> beanClass) {
		// Previously we setProxyTargetClass(true) in the constructor, but that has too
		// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
		// aspects. I'm not entirely happy with that as there is no good reason not
		// to advise aspects, except that it causes advice invocation to go through a
		// proxy, and if the aspect implements e.g the Ordered interface it will be
		// proxied by that interface and fail at runtime as the advice method is not
		// defined on the interface. We could potentially relax the restriction about
		// not advising aspects in the future.
		return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
	}

做了2件事:

 1.调用父类的isInfrastructureClass方法,看是不是基础类(Adive、PointCut、Advisor、AopInfrastructureBean)

2.调用isAspect方法看是不是有@Aspect注解,是否有$ajc开头的成员变量

2.2 shouldSkip方法

源码:

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names

        // 1.找到所有候选的通知器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();

        // 遍历通知器
		for (Advisor advisor : candidateAdvisors) {

            // 如果该通知器是 AspectJPointcutAdvisor 类型
			if (advisor instanceof AspectJPointcutAdvisor) {

                //并且该通知器的通知的切面名称和bean的名字相同
				if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {

                    // 就返回 true
					return true;
				}
			}
		}

        // 否则调用父类的shouldSkip方法返回false。
		return super.shouldSkip(beanClass, beanName);
	}

做了2件事:

1.找到所有候选的通知器Advisor。

2.遍历通知器,如果该通知器Advisor是 AspectJPointcutAdvisor 类型,并且该Advisor通知器的通知的切面名称和bean的名字相同,就返回 true,否则调用父类的shouldSkip方法返回false。

2.3 findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.

        // 获取容器中所有实现了Advisor 接口的Bean
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.

        // 根据注解创建通知器
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		return advisors;
	}

 做了2件事:

1.获取容器中所有实现了Advisor接口的Bean。

通过BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);

方法获取到所有的Advisor类型的Bean的名称

2.找到所有@Aspect修饰的bean。

通过BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);方法获取BeanFactory中所有的类,遍历这些类,调用isAspect方法找出有@Aspect注解的Bean作为候选,解析出这个@Aspect类的切点@pointCut和增强方法们,即是解析出Advisor(advice增强方法处理逻辑+该方法切入点pointcut)

详细看一下this.aspectJAdvisorsBuilder.buildAspectJAdvisors方法

2.4 BeanFactoryAspectJAdvisorsBuilder类的buildAspectJAdvisors方法

源码:

public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

        // 如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName为空
		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new LinkedList<Advisor>();
					aspectNames = new LinkedList<String>();

                    // 获取BeanFactory中所有的类

					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);

                    // 遍历这些类
					for (String beanName : beanNames) {
						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.
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}

                        // 调用isAspect方法找出有@Aspect注解的Bean作为候选

						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

                        //解析出这个@Aspect类的切点@pointCut和增强方法们
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
   
                        // 如果这个bean是单例,则加入到advisor缓存中
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
                                //否则加入到切面工厂缓存中
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}


        
		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}

        // 如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName不为空
		List<Advisor> advisors = new LinkedList<Advisor>();

        // 遍历BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName
		for (String aspectName : aspectNames) {

            
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);

            // 如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中有这个切面beanName
			if (cachedAdvisors != null) {
                // 加入到要返回的列表中
				advisors.addAll(cachedAdvisors);
			}
			else {

            // 如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中没有这个切面beanName
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);

                // 生成一个advisor再加入到要返回的列表中
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}

分2个部分:

第一部分:

如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName为空:

用BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false)方法获取BeanFactory中所有的beanName。

遍历这些beanName,调用isAspect方法,找到有@Aspect注解修饰bean,调用ReflectiveAspectJAdvisorFactory类的getAdvisors方法,解析出这个类中所有的Advisors。

如果这个beanName是单例则加入到BeanFactoryAspectJAdvisorsBuilder的advisor缓存中,否则加入到BeanFactoryAspectJAdvisorsBuilder的切面工厂缓存中。

把解析出来的advisor加入到返回列表中

把所有有@Aspect注解的beanName注册到AnnotationAwareAspectJAutoProxyCreator$BeanFactoryAspectJAdvisorsBuilder

的aspectBeanNames属性中,这个属性是个list。

第二部分:

如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName不为空:

遍历BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName。

如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中有这个切面beanName,则将缓存中的advisor加入到要返回的列表中。

如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中没有这个切面beanName,则生成一个advisor再加入到要返回的列表中。

2.5 getAdvisors方法解析出Advisors

额应该不需要解释Advisor是什么吧,通俗接地气的说Advisor=advice+pointcut,就是某个增强方法在那个切入点执行逻辑。

ReflectiveAspectJAdvisorFactory类的getAdvisors方法

源码:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new LinkedList<Advisor>();

        // 解析出这个@Aspect注解修饰的bean有哪些方法,包括其父类的方法
		for (Method method : getAdvisorMethods(aspectClass)) {

            // 根据每个方法解析出这个方法有哪些pointCut并且封装成Advisor返回
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.

        // 如果属性上有@DeclareParents注解,根据此注解生成Advisor
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

做了4件事:

1.得到@Aspect注解修饰的class和beanName,校验class。

2.得到该Bean所有的方法,包括其父类方法,每个方法调用getAdvisor方法,解析出该方法有哪些切入点pointcut,封装成InstantiationModelAwarePointcutAdvisorImpl返回。

3.如果方法解析出的的Advisor为空,并且lazySingletonAspectInstanceFactory是懒加载,则生成一个SyntheticInstantiationAdvisor

4.得到该Bean所有的filed,调用getDeclareParentsAdvisor解析,如果属性上有@DeclareParents注解,根据此注解生成DeclareParentsAdvisor

三、postProcessAfterInitialization 

AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor,每一个bean初始化之后,会调用它的postProcessAfterInitialization ,而他自己没有该方法,所以是调用他父类AbstractAutoProxyCreator类的postProcessAfterInitialization 方法处理需要代理的bean。

方法调用栈:

postProcessAfterInitialization 方法源码:

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

做了2件事:

1.如果bean为空,直接返回。

2.如果bean不为空,是工厂bean则在bean的名字前加上$符号,如果earlyProxyReferences中(当 Bean 被循环引用, 并且较早就暴露了, 则会通过 getEarlyBeanReference 来创建代理类。在初始化后置方法 postProcessAfterInitialization 中通过判断 earlyProxyReferences 中是否存在 beanName 来决定是否需要对 target 进行动态代理)没有这个bean,则调用wrapIfNecessary方法判断该bean是否需要被代理,需要则生成代理对象放回,不需要代理就返回原bean。

 3.1 AbstractAutoProxyCreator类的wrapIfNecessary方法

源码:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		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;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

做了4件事:

1.beanName不为空,并且targetSourcedBeans中已经有了这个beanName,则直接返回,不创建代理对象。

2.如果这个beanName在advisedBean中(表示该类已经做个AOP解析了,不需要创建代理)存的false,直接返回,不创建代理对象。

3.如果这是一个永不需要创建代理对象的基础类,或者掉过,直接返回,不创建代理对象。

4.调用getAdvicesAndAdvisorsForBean方法得到advices和Advisors,调用createProxy方法创建代理对象。调用的这两个方法会专门写一篇创建代理对象的博客来介绍

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值