Spring中AOP源码浅析③

结合Spring中AOP源码浅析① Spring中AOP源码浅析② 这两篇文章我们知道AOP的实现其实是通过引入AnnotationAwareAspectJAutoProxyCreator这个类(注解感知AspectJ自动代理创建器  BeanName:org.springframework.aop.config.internalAutoProxyCreator)去实现的。实际他的底层也是一个InstantiationAwareBeanPostProcessor后置处理器。结合两篇文章,简单画一下它的实现过程。

Spring中AOP源码浅析③_第1张图片

那么就来分析一下InstantiationAwareBeanPostProcessor 这个后置处理器的前置方法和后置方法分别做了哪些事情。

前置方法在resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd);这里执行,查看源码

	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            //确保此时已经解析了Bean
            //非合成Bean并且是InstantiationAwareBeanPostProcessors类型的后置处理器
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                //目标Bean的class
				Class targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
                    //执行后置处理器的前置方法
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

我们只需要关注bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);这个方法

	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) {
        //遍历所有后置处理器
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //只拿到InstantiationAwareBeanPostProcessor类型的后置处理器
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                //执行前置方法
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

继续从Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);这里进去

这里InstantiationAwareBeanPostProcessor 这个处理器有多个实现类,我们只关注AOP相关的AbstractAutoProxyCreator

因为从Spring中AOP源码浅析①这篇文章中有分析得到 AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator

继续跟进代码

	@Override
	public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            //判断增强Bean是否包含当前key,业务Bean肯定不在这里
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
            //判断是否为基础组件(通知类切面类等)、判断是否应该跳过
            //shouldSkip:找到所有增强器Advisors(即通知方法),第一次会解析切面类并创建增强器
            //对于业务Bean  这里返回false
			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.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				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;
	}

 

targetSource是一个接口,对于业务Bean来说,如果实现这个接口,则会执行下面的业务创建代理对象,对于普通业务Bean 这一步返回的是空,暂时不关注这一块。

这一步就已经完成了前置处理,主要就在shouldSkip()这个方法里面,对切面类进行解析并创建了增强器Advisors,赋值给了全局变量。

	@Override
	protected boolean shouldSkip(Class beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names考虑优化 通过 缓存缓存切面名字
        // findCandidateAdvisors这一步就是查找所有增强器
		List candidateAdvisors = findCandidateAdvisors();
        //遍历增强器  查看切面名字是否和传入的Bean相同
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
        //父类没有任何操作  直接返回False
		return super.shouldSkip(beanClass, beanName);
	}

findCandidateAdvisors() 需要在深入看一下具体是如何拿到增强器的。他这里调用了父类的查找方法。

	@Override
	protected List findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
        //调用父类  第一次没有获取到
		List advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
        //通过 aspectJAdvisorsBuilder 去创建
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

第一次获取不到的,然后通过this.aspectJAdvisorsBuilder.buildAspectJAdvisors()去构建,进去看一下

	/**
	 * Look for AspectJ-annotated aspect beans in the current bean factory,
	 * and return to a list of Spring AOP Advisors representing them.
	 * 

Creates a Spring Advisor for each AspectJ advice method. * @return the list of {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */ public List buildAspectJAdvisors() { List aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { .......

内容很多,我们就只关注重点,重点就是他返回的是List,返回的是增强器。

看一下注释,翻译下:在当前的bean工厂中查找带有AspectJ注释的切面bean(可能不止一个),然后返回Advisor列表代表他们。 为每个AspectJ通知方法创建一个Spring Advisor。

结合debug,这里对我们的切面类进行了解析,并把每个方法封装成了一个Advisor。结合我们的切面类看一下。

//日志切面类
@Aspect
public class LogAspects {
    //切点
	@Pointcut("execution(public void com.csdn.asong.aop.FunAspects.*(..))")
	public void pointCut(){};
	
	//前置 @before代表在目标方法执行前切入, 并指定在哪个方法前切入
	@Before("pointCut()")
	public void logStart(){
		System.out.println("logStart 业务准备执行....");
	}
    //后置
	@After("pointCut()")
	public void logEnd(){
		System.out.println("logEnd 业务执行结束......");
		
	}
    //返回
	@AfterReturning("pointCut()")
	public void logReturn(){
		System.out.println("logReturn 正常返回......");
	}
    //异常
	@AfterThrowing("pointCut()")
	public void logException(){
		System.out.println("logException 运行异常......");
	}
	//环绕
	@Around("pointCut()")
	public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
		System.out.println("@Around:执行目标方法之前...");
        //执行目标业务方法
		Object obj = proceedingJoinPoint.proceed();
		System.out.println("@Around:执行目标方法之后...");
		return obj;
	}
}

所以在List aspectNames = this.aspectBeanNames;我们找到了logAspects ,之后又把@Before、@After、@AfterReturning、@AfterThrowing、@Around这些注解标注的方法封装成了List。所以返回的List长度应该是5。经过debug我们也能看到如下结果:

Spring中AOP源码浅析③_第2张图片

至此,对于需要增强的业务Bean来说,我们的前置方法就已经完成了他的功能。

所以前置方法完成的任务是什么?对于业务Bean来说,前置方法这一步返回的是空的,但是它完成了解析切面类,拿到了增强器。上一篇文章提到后置处理的方法执完毕后才拿到了真正的代理业务Bean对象,所以增强代码的织入,代理对象的生成由后置处理方法postProcessAfterInstantiation()去完成。

继续 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 从这里点进去看,找到 InstantiationAwareBeanPostProcessor 处理器执行的后置方法

//遍历所有后置处理器执行相应的后置方法		
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}

这里是遍历所有+执行所有,我们重点关注的是AnnotationAwareAspectJAutoProxyCreator这个处理器,可以加个断点进去看看执行过程

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
                //进入到了这里:包装Bean如果有必要的话
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

从这里wrapIfNecessary(bean, beanName, cacheKey);再进去,这里我们就找到了相应生成代理对象的代码

	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;
		}

		// Create proxy if we have advice. 创建代理如果我们有通知
        // 这里是生成代理对象的过程
        //specificInterceptors 特殊拦截器:实际是所有的Advices和Advisors
		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;
	}

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);这一步是获取所有的特殊拦截器,实际是Advisor增强器,并对其进行排序,因为我们的增强器对应的就是相应切面类里面的通知方法,每个方法都有相应的拦截顺序。

createProxy() 这一步是创建代理,从这一步进去,发现我们的代理对象是通过ProxyFactory 代理工厂生成的。代理工厂就是负责把所有的增强器通过动态代理的方式织入到业务Bean的方法前后。

	protected Object createProxy(Class beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

        //前期的准备验证工作
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
        //将特殊拦截器转换为增强器
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

        //最后一步从代理工厂获取代理对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}

前期只是准备验证工作,我们关注最后一句proxyFactory.getProxy(getProxyClassLoader());

	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

从这里再进去 是 CglibAopProxy ,因为我们业务Bean 没有响应的接口,所以使用了Cglib创建动态代理的方式。

因为从实现类我们可以看到两个,分别是JDK动态代理和Cglib动态代理

Spring中AOP源码浅析③_第3张图片

createAopProxy()的内部实现也可以清楚地看到具体的选择方法:

	@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);
		}
	}

至此我们就分析完了后置处理器 生成代理对象的过程。至于这两种代理方式以后有空再细细分析。

你可能感兴趣的:(Spring,spring,java,aop)