Spring AOP 源码解析

2,380 阅读4分钟

Spring framework版本 5.3.x
博客地址:blog.ljbmxsm.com/

1. 基本概念

AOP 是面向切面|面向方面编程的简称,Aspect-Oriented Programming。 Aspect 是一种模块化机制,是用来描述分散在对象,类,函数中的横切关注点。

  • 基础: 待增强对象或者目标对象
  • 切面: 包含对基础的增强应用
  • 配置: 可以看成一种编织,通过在AOP体系中提供这个配置环境,将基础和切面结合起来,从而完成切面对目标对象的编织实现
  • Advice(通知): 定义在连接点做什么,为切面增强提供织入接口。在Spring AOP 中,它主要描述Spring AOP 围绕方法调用而注入的切面行为。
  • Pointcut(切点):决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强的方法集合。
  • Advisor(通知器):完成对目标方法的切面增强设计(advice)和关注点的设计以后,需要一个对象把它们结合起来,完成这个作用的就是Advisor(通知器)。通过Advisor ,可以定义应该使用那个通知并在哪个关注点使用它。

2. 源码解析

源码解析以注解为分析

通过 @EnableAspectJAutoProxy 注解开开启AOP:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * false:表示使用java代理
	 * true:表示使用cglib代理
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 代理的暴露方式,解决内部调用不能使用代理的场景,默认为false
	 */
	boolean exposeProxy() default false;
}

注解使用 @Import 注解引入了 AspectJAutoProxyRegistrar 类,接下来跟踪一下 AspectJAutoProxyRegistrar

2.1 AspectJAutoProxyRegistrar源码解析

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
        //注册AnnotationAwareAspectJAutoProxyCreator
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		
        //读取配置的注解EnableAspectJAutoProxy属性
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}

通过源代码发现 AspectJAutoProxyRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,在Spring容器启动的时候会调用 ImportBeanDefinitionRegistrar#registerBeanDefinitions 方法来注入 AnnotationAwareAspectJAutoProxyCreator

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

注册的Bean名称为:org.springframework.aop.config.internalAutoProxyCreator

最终调用的是 AopConfigUtils#registerOrEscalateApcAsRequired 方法

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
		Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
			int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
			int requiredPriority = findPriorityForClass(cls);
			if (currentPriority < requiredPriority) {
				apcDefinition.setBeanClassName(cls.getName());
			}
		}
		return null;
	}

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

到这里 AnnotationAwareAspectJAutoProxyCreator 类注册完成。接下来看 AnnotationAwareAspectJAutoProxyCreator 是如何创建代理类的。

2.2 AnnotationAwareAspectJAutoProxyCreator源码解析

首先看一下类的继承关系:

通过继承关系发现实现了 SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware,InstantiationAwareBeanPostProcessor,BeanPostProcessor。 下面看一下接口执行的方式:

AbstractAutoProxyCreator 重写了 BeanPostProcessor#postProcessAfterInitialization方法 和InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法 ,接下来详细分析一下这个两个方法:

2.2.1 AbstractAutoProxyCreator#postProcessBeforeInstantiation
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		//获取bean的key
        Object cacheKey = getCacheKey(beanClass, beanName);
		//判断bean是否已经处理过了,处理了的会放在targetSourcedBeans
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			//判断是否包含了advise
            if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
            //判断类型和是否应该跳过
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}
		
		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;
	}
2.2.1 AbstractAutoProxyCreator#postProcessAfterInitialization

看一下这个方法的调用链:

下面看一下 AbstractAutoProxyCreator#postProcessAfterInitialization 方法:

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

主要生成代理类的方法是 wrapIfNecessary 下面来看一下具体实现:

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

	// 获取通知和通知器
	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;
}

getAdvicesAndAdvisorsForBean 方法最终调用的是 AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean 方法,进一步调用的是**AbstractAdvisorAutoProxyCreator#findEligibleAdvisors** 方法:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //查找候选的Advisor
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //过滤出来可用的
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}
  • findCandidateAdvisors

    #AnnotationAwareAspectJAutoProxyCreator实现类
    @Override
    protected List<Advisor> findCandidateAdvisors() {
    	// 根据父类规则查找所有的Spring advisor
    	List<Advisor> advisors = super.findCandidateAdvisors();
    	
    	if (this.aspectJAdvisorsBuilder != null) {
            //查找所有的Aspect(标注了注解的@Aspect的Bean) 并且解析
    		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    	}
    	return advisors;
    }
    
  • findAdvisorsThatCanApply

    protected List<Advisor> findAdvisorsThatCanApply(
    		List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
    	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    	try {
    		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    	}
    	finally {
    		ProxyCreationContext.setCurrentProxiedBeanName(null);
    	}
    }
    

到这里这两个方法就分析完成了。当获取到了通知和通知器就开始创建代理对象

2.2.2 AbstractAutoProxyCreator#createProxy创建代理类
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);

    //判断使用jdk代理还是CGLIB代理
	if (proxyFactory.isProxyTargetClass()) {
		// Explicit handling of JDK proxy targets (for introduction advice scenarios)
		if (Proxy.isProxyClass(beanClass)) {
			// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
			for (Class<?> ifc : beanClass.getInterfaces()) {
				proxyFactory.addInterface(ifc);
			}
		}
	}
	else {
		// No proxyTargetClass flag enforced, let's apply our default checks...
		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);
	}

	// Use original ClassLoader if bean class not locally loaded in overriding class loader
	ClassLoader classLoader = getProxyClassLoader();
	if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
		classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
	}
    //创建代理对象
	return proxyFactory.getProxy(classLoader);
}

3. Spring 创建Bean的简易流程

Bean的获取主要是通过BeanFactory获取,但是创建工作主要有BeanPostProcessor完成。代理类的创建就是通过 AbstractAutoProxyCreator 类执行实现

postProcessBeforeInstantiation 方法和 postProcessAfterInitialization 方法来对改变创建对象和对对象进行增强实现代理。

4. 总结

Spring AOP的整个启动过程:

  • 创建 BeanFactoryAdvisorRetrievalHelperAdapter 类(通知器检索适配器)和 BeanFactoryAspectJAdvisorsBuilderAdapter
  • 调用 AbstractAutoProxyCreator#postProcessBeforeInstantiation 方法查找所有的Advisor和切面,将切面构建成Advisor
  • 调用 AbstractAutoProxyCreator#postProcessAfterInitialization 方法,从缓存取出所有的将所有的增强器,创建代理工厂,并织入增强器,创建代理对象

Tips: 主要是通过实现 postProcessBeforeInstantiation 和 postProcessAfterInitialization 这两个方法来判断是否创建代理对象和如何创建代理