浅析AOP源码(一)

转载自:https://blog.csdn.net/moreevan/article/details/11977115/
    https://blog.csdn.net/qq_38182963/article/details/78747404
    https://blog.csdn.net/xiaoxufox/article/details/54695200
    https://mp.weixin.qq.com/s?__biz=MzAxNjk4ODE4OQ==&mid=2247484741&idx=1&sn=42310e59d06abc3fa08454949e3a17aa&chksm=9bed2437ac9aad21cb5e635bef607e1c0631ea9e8ca88fed8f65ecb61ca69f1951679d84ee41&scene=21#wechat_redirect

  AOP(Aspect-Oriented Programming)面向切面的编程,在平时的开发过程中,AOP其实用到的地方一般有:

①用来做日记的处理
②方法的调用统计
③业务层面的读写分离(例如自定义的Annotation+AOP可以实现切换数据源)
④自定义权限拦截器

  在Spring框架中,AOP则发挥了不少功效,例如spring的事务。
  AOP具体的介绍移步:https://blog.csdn.net/zero__007/article/details/46765191


  在介绍代码之前先介绍Spring Aop中一些核心类,大致分为三类:
  • advisor:顾问的意思,advisor是Spring中切面的体现形式,封装了spring aop中的切点和通知。包括有:

DefaultPointcutAdvisor: 默认切面顾问,比较灵活。可自由组合切面和通知。
InstantiationModelAwarePointcutAdvisorImpl: springboot自动装配的顾问类型,也是最常用的一种顾问实现。在注解实现的切面中,所有@Aspect注释的类,都会被解析成该对象。

  • advice:通知,也就是 Spring AOP 中增强的方法。包括有:

AspectJMethodBeforeAdvice:前置通知,AspectJ中 before 属性对应的通知(@Before标注的方法会被解析成该通知),在切面方法执行之前执行。
AspectJAfterReturningAdvice:后置通知,AspectJ中 afterReturning 属性对应的通知(@AfterReturning 标注的方法会被解析成该通知),在切面方法执行之后执行,如果有异常,则不执行。注意:该通知与AspectJMethodBeforeAdvice对应。
AspectJAroundAdvice:环绕通知,AspectJ中 around 属性对应的通知(@Around标注的方法会被解析成该通知),在切面方法执行前后执行。
AspectJAfterAdvice:返回通知,AspectJ中 after 属性对应的通知(@After 标注的方法会被解析成该通知),不论是否异常都会执行。

  • advisorCreator:代理机制,抽象类AbstractAutoProxyCreator的每个实现类代表着一种代理机制。默认情况下只使用一种代理机制。 继承 spring ioc的扩展接口 beanPostProcessor,主要用来扫描获取 advisor。包括有:

AbstractAutoProxyCreator:代理机制抽象类,Spring 为Spring AOP 模块暴露的扩展类,也是 AOP 中最核心的类。Nepxion Matrix 框架便是基于此类对AOP进行扩展和增强。
AspectJAwareAdvisorAutoProxyCreator:Aspectj的实现方式,也是Spring Aop中最常用的实现方式,如果用注解方式,则用其子类AnnotationAwareAspectJAutoProxyCreator。
AnnotationAwareAspectJAutoProxyCreator:目前最常用的AOP使用方式。spring aop 开启注解方式之后,该类会扫描所有@Aspect()标准的类,生成对应的adviosr。目前SpringBoot框架中默认支持的方式,自动配置。


  在Spring中,使用AOP需要在xml中添加 Aop:configAop:aspectj-autoproxy 标签。Spring会使用AopNamespaceHandler#init注册这类标签解析器beanDefinitionparser:

public class AopNamespaceHandler extends NamespaceHandlerSupport {

   /**
    * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
    * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
    * and '{@code scoped-proxy}' tags.
    */
   @Override
   public void init() {
      // In 2.0 XSD as well as in 2.1 XSD.
      registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
      registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

      // Only in 2.0 XSD: moved to context namespace as of 2.1
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
   }

}

  AspectJAutoProxyBeanDefinitionParserConfigBeanDefinitionParser都是BeanDefinitionParser的子类。
  在解析为BeanDefinition时,BeanDefinitionParserDelegate#parseCustomElement会调用到这个BeanDefinitionParser的parse方法:

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    String namespaceUri = this.getNamespaceURI(ele);
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    } else {
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
}

  来关注看下AspectJAutoProxyBeanDefinitionParser

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {

   @Override
   public BeanDefinition parse(Element element, ParserContext parserContext) {
      //解析aspectj-autoproxy标签
      AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
      //解析子标签
      extendBeanDefinition(element, parserContext);
      return null;
   }
    
    // …
}

  AopNamespaceUtils类:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
      ParserContext parserContext, Element sourceElement) {
   //注册bean:AnnotationAwareAspectJAutoProxyCreator
   BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
         parserContext.getRegistry(), parserContext.extractSource(sourceElement));
   //设置proxy-target-class和expose-proxy这两个属性
   useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
   //注册到ParserContext
   registerComponentIfNecessary(beanDefinition, parserContext);
}

  下面是关键类AnnotationAwareAspectJAutoProxyCreator
在这里插入图片描述  AnnotationAwareAspectJAutoProxyCreator继承了SmartInstantiationAwareBeanPostProcessorAbstractAutoProxyCreator中对SmartInstantiationAwareBeanPostProcessor的接口有实现:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    // ...
    
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
            //advisedBeans用于存储不可代理的bean,如果包含直接返回
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
            //isInfrastructureClass判断是否是Advisor、Advice、AopInfrastructureBean,如果是,则不能被代理
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

        //到这里说明该bean可以被代理,所以去获取自定义目标类,如果没有定义,则跳过。
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
                //获取bean适配的Advice
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                //创建代理
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
                //如果最终可以获得代理类,则返回代理类,直接执行实例化后置通知方法
				return proxy;
			}
		}

		return null;
	}

	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

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

   //…
}

  在bean实例化前和后会调用SmartInstantiationAwareBeanPostProcessor接口方法,看代码注释就大致知道是什么过程。来看 shouldSkip 方法,shouldSkip会跳过切面类,怎么判定呢?在子类AspectJAwareAdvisorAutoProxyCreator中:

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
   // TODO: Consider optimization by caching the list of the aspect names
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   for (Advisor advisor : candidateAdvisors) {
      if (advisor instanceof AspectJPointcutAdvisor) {
         if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
            return true;
         }
      }
   }
   return super.shouldSkip(beanClass, beanName);
}

  通过findCandidateAdvisors()方法来获取所有的候选 advisor:

@Override
protected List<Advisor> findCandidateAdvisors() {
   //获得 Advisor 实现类
   List<Advisor> advisors = super.findCandidateAdvisors();
   // 处理@Aspect注解类, 解析成Advisor
   advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   return advisors;
}

  buildAspectJAdvisors()方法会解析@Aspect注解类,将该类所有被@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut注解的方法封装成advisor。

  可以看出来,创建advisor的逻辑发生在扩展接口中的postProcessBeforeInstantiation,实例化之前执行,如果有自定义的TargetSource指定类,则直接生成代理类,这种情况使用不多,常规代理类还是在postProcessAfterInitialization中创建,也就是 IOC 最后一个扩展方法。
  在bean实例化之后,调用postProcessAfterInitialization()来生成代理类,来看下里面的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;
		}

		//获取适合的advise
		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;
	}

  先获取到合适的advisor,如果不为空,则调用createProxy生成代理类:

	protected Object createProxy(
			Class<?> beanClass, String beanName, 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);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}

		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

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

		return proxyFactory.getProxy(getProxyClassLoader());
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值