Spring AOP原理解析

AOP原理解析

要想使aop生效需要@EnableAspectJAutoProxy支持,我们查看注解内部@Import(AspectJAutoProxyRegistrar.class)
@Import也是讲bean交给spring容器管理的一种方式,常见于第三方bean。 AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar,
ImportBeanDefinitionRegistrar也是一种bean交给spring容器的方式。会由指定的后置处理器调用registerBeanDefinitions方法,直接将bean封装成为
beanDefinition然后注册到容器中,后续由遍历创建bean.

	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

具体这个方法在哪里调用呢?
我们知道配置类解析是由ConfigurationClassPostProcessor来做的,做配置类的解析时会解析@import注解等等,
封装ConfigurationClass,然后解析成为BeanDefinition,然后进行注册。所以在进行BeanDefinition后置处理器注册的时候
会调用这个方法。这个方法具体的作用是创建一个
beanDefinition(org.springframework.aop.config.internalAutoProxyCreator)cls:AspectJAwareAdvisorAutoProxyCreator进行注册:

	RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;

AspectJAwareAdvisorAutoProxyCreator是属于InstantiationAwareBeanPostProcessor的实现类,所以在进行创建bean创建相关的后置处理器的时候会进行实例化
并对容器的创建进行增强,实例化的步骤这里省略。

后续的步骤就是进行我们自定义创建bean的初始化操作了
我们主要关注aspect类和做增强的类的创建与初始化。在我们创建bean的过程中,会循环遍历已创建的后置处理器
在bean的初始化的方法前后做增强。我们关注aop相关的AspectJAwareAdvisorAutoProxyCreator做的增强
首先是前置:

if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}

在实例第一个自定义bean的时候,在创建好了bean之后进行bean的初始化方法后置增强的时候会去判断当前bean是否需要进行做代理,会进入shouldSkip方法进行判断, 这个方法会对我们的aspect和advisor进行缓存。在方法findCandidateAdvisors中
会调用this.aspectJAdvisorsBuilder.buildAspectJAdvisors()的方法。这个将@Aspect注解的beanName放到BeanFactoryAspectJAdvisorsBuilder的List aspectBeanNames;
将一个个方法封装成为advisor放到Map<String, List> advisorsCache = new ConcurrentHashMap<>();中

List<String> aspectNames = this.aspectBeanNames;//缓存的apectBean的名字集合
		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
							//找到当前所有已创建和未创建的bean的name数组
							//遍历数组找到@aspect的类
					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;
						}
						if (this.advisorFactory.isAspect(beanType)) {
						//判断是否属于aspect的类,属于将beanName缓存,然后找到当前类中的所有的advisor,并缓存
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								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;
				}
			}
		}

再看被增强类的初始化:主要是看初始化方法的后置处理:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && 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;
		}
        如果这个类有advice的话就创建代理类
		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
		//标识当前类是advisedBean
			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;
	}

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
这个方法会为当前bean找到合适的advisor。通过我们定义在pointCut上面的expression来匹配。如果能匹配到advisor的话
同时会添加一个默认的advisor,这个advisor为单例并对所有的bean都匹配,然后对advisor进行排序

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	    //找到所有的advisor,先从缓存找,找不到去创建
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//为bean找到合适的advisor集合
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		//匹配advisor不为空,添加一个默认的advisor到第一位,匹配所有的bean
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
		    //对匹配的advisor进行排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

关于采用何种代理类,如果增强类为接口类型的话就默认此采用jdk的动态代理,其他采用cglib的动态代理方式

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

真正在容器中保存的对象是动态代理的对象,这个当我们在debug获取容器对象的时候能够很清楚的看到其实拿到的是代理对象

=======================
当我们在调用增强的方法的时候,我们以CGLIB动态代理为例,当我们调用我们被增强的方法时实际调用的是
DynamicAdvisedInterceptor.intercept方法首先会拿到一个advisor链
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
因为通过容器拿到的是代理类,所有不管是非增强方法还是增强方法都会被intercept拦截
,只不过非增强方法获取advisor链拿到的是默认的advisor,这个方法并不会做任何增强。

若执行方法为增强方法,则这个链的顺序为:
0.exposeInvocationInterceptor 这个是默认的advisor
1.afterThrowingAdvice
2.afterReturningAdvice
3.afterAdvice
4.aroundAdvice
5.beforeAdvice

所有的advice的调用是压栈式的,类似于递归调用

	public Object proceed() throws Throwable {
		//	We start with an index of -1 and increment early
		//index从-1开始,当最后一个advisor的proceed方法执行完成,index=size-1,开始执行目标方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
		每递归一次index+1,取出下一个advisor,然后调用proceed方法
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			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 {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

具体执行流程图:
Spring AOP原理解析

   @Pointcut("execution(* com.learning.controller.*.*(..))")
   public void pointCut(){}

   @Before("pointCut()")
   public void doBefore(){
       System.out.println("OrderAspect doBefore.........");
   }

   @After("pointCut()")
   public void doAfter(){
       System.out.println("OrderAspect doAfter............");
   }

   @AfterReturning("pointCut()")
   public void doAfterReturning(){
       System.out.println("OrderAspect doAfterReturning......................");
   }

   @AfterThrowing("pointCut()")
   public void doAfterThrowing(){
       System.out.println("OrderAspect doAfterThrowing..................");
   }
   @Around("pointCut()")
   public void doAround(ProceedingJoinPoint pjp) throws Throwable {
       System.out.println("OrderAspect doAround..................begin");
       pjp.proceed();
       System.out.println("OrderAspect doAround..................end");
   }

执行结果:
OrderAspect doAround…begin
OrderAspect doBefore…
OrderController execute method…
OrderAspect doAround…end
OrderAspect doAfter…
OrderAspect doAfterReturning…