SpringAop源码详解

Spring AOP 源码详解

在实际开发过程中,会有需要用到自动事务管理,自动日志打印等需求,那么通过一个注解或者配置,实现自动对类进行功能增强就非常有必要。Spring Aop就提供了这样的功能,实现对目标类的成员方法进行增强

SpringAop和AspectJ二者的关系

1、AspectJ是一个面向切面的Java框架,他定义了一套切面语言,如@Aspect、@Before、@AfterReturning、@AfterThrowing、@After、@Around等,还提供了强大的切面表达式,如(如@PointCut execution(* com.example.service..(…))),提供了强大的切面解析框架。
2、SpringAop提供了创建代理的能力,Spring定义了两个重要的核心接口,Advisor(PointCut+Advice通知)的组合,定义了在哪个类哪个方法增强哪个方法及增强逻辑,Advice是一个包含通知逻辑的拦截器,等同于AspectJ里的@Before等注解的实际类型。
同时Spring通过ProxyFactory代理工厂来创建目标类型的代理,可以选择(CglibAopProxy\JdkAopProxy)两种代理,我们一般在启动类配置@EnableAspectJAutoProxy(proxyTargetClass =true) // 强制使用CGLIB代理 不需要接口 生成被代理类的子类
代理工厂类:DefaultAopProxyFactory.java

/**
	 * 决定是JDK动态代理 还是CGLIB
	 * config.isProxyTargetClass() ->
	 * 最关键的开关(由 @EnableAspectJAutoProxy(proxyTargetClass = true)控制) 是否开启CGLIB  默认值false
	 * @param config the AOP configuration in the form of an
	 * AdvisedSupport object
	 * @return
	 * @throws AopConfigException
	 */
	@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);
		}
	}

这样两个组件的分工协作实现了完整的AOP功能

SpringAop增强的过程

1、创建代理的入口

有循环依赖的类和正常的类,AOP代理生成位置不一样。
有循环依赖,代理生成位置在获取早期bean引用的方法里:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   
   
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   
   
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
   
   
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
   
   
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
}

这里会有一个BeanPostPorcessor,AnnotationAwareAspectJAutoProxyCreator,类里面的getEarlyBeanReference方法用来获取早期引用,如果有代理就要增强后返回。

// 进行代理增强
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
   
   
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		// 代理生成的核心方法
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

没有循环依赖
代理生成的位置在调用完初始化方法,后置处理器里

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
   
   
   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
   
   
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
   
   
         return result;
      }
      result = current;
   }
   return result;
}

这里有一个BeanPostProcessor,AbstractAutoProxyCreator,这个类和上面的类是父子关系,调用的方法也一样,可以看到,最终都是调用wrapIfNecessary方法来创建代理

	/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   
   
		if (bean != null) {
   
   
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
   
   
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

2、获取切面类,判断当前目标类需不需要代理,(切面类不需要代理,没有切入规则的类不需要代理),上面两个生成代理方法的里面都有个关键逻辑

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

isInfrastructureClass(beanClass)用来判断当前类是不是切面的子类

shouldSkip(beanClass, beanName)

就是关键的解析切面类,判断切入规则

AspectJAwareAdvisorAutoProxyCreator.class

@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 &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
   
   
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

findCandidateAdvisors() 就是查找所有的切面类

AspectJAwareAdvisorAutoProxyCreator.class

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

buildAspectJAdvisors() 方法进行真正的切面解析

/**
	 * 寻找当前bean工厂注解了AspectJ注解的类,并返回aop切面列表代表他们
	 */
	public List<Advisor> buildAspectJAdvisors() {
   
   
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
   
   
			synchronized (this) {
   
   
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
   
   
					List<Advisor> advisors = new ArrayList
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值