Spring AOP源码解析一:AOP代理重要bean---AnnotationAwareAspectJAutoProxyCreator的创建

       最近在学习Spring AOP,就顺便看了一下Spring AOP的源码,这里记录一下,防止七秒钟的记忆。之前写过一篇关于Spring AOP的基本使用:Spring AOP 基本概念和使用,建议大家先去观看一下,再回来阅读这篇文章。

       AOP是一种思想和理念,可以使用这种思想来简化代码开发的耦合性和难度,有句话说的好,天上飞的理念,必有落地的实现,那么实现了AOP这个思想的具体实现由Spring AOP和AspectJ技术,他们都是根据AOP的思想实现的。

       Spring AOP和AspectJ的关系?
       springAop、AspectJ都是Aop的实现,Spring AOP使用XML的格式进行配置的,SpringAop有自己的语法,但是语法复杂,所以SpringAop借助了AspectJ的注解(记住只是使用到了AspectJ的注解,而进行注解的解析工作是Spring内部实现的,所以Spring AOP只是借助了AspectJ的注解而已)。

spring AOP提供两种编程风格

@AspectJ support ------------>利用aspectj的注解

Schema-based AOP support ----------->xml aop:config 命名空间

证明:spring通过源码分析,我们可以知道spring底层使用的是JDK或者CGLIB来完成的代理,并且在官网上spring给出了aspectj的文档,和springAOP是不同的

      关于Spring AOP的使用,Spring官网是推荐使用AspectJ来进行的,这里的源码分析也是分析基于注解使用的Spring AOP。

      要能够使用AspectJ的注解,首先需要在配置上面添加@EnableAspectJAutoProxy,来增加对注解的解析,首先来看一下这个@EnableAspectJAutoProxy的源码。

代码块1:@EnableAspectJAutoProxy源码

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

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	boolean exposeProxy() default false;
}

      可以看到EnableAspectJAutoProxy注解上面有使用@Import向容器中导入了bean,这里就牵涉到@Import的使用了,感兴趣的同学可以参考:Spring为IOC容器注入Bean的方式,这里使用的是@Import + ImportBeanDefinitionRegistrar的方式向Spring容器中注入bean,下面看一下AspectJAutoProxyRegistrar的源码。

代码块2:AspectJAutoProxyRegistrar源码

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//1.注册AnnotationAwareAspectJAutoProxyCreator的BeanDefinition
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		//2.获取原注解也就是EnableAspectJAutoProxy上面设置的属性值
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		
		if (enableAspectJAutoProxy != null) {
			//3.设置proxyTargetClass属性
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			//4.设置exposeProxy属性
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}

      第1步注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,此步骤很关键,具体看代码块3中的registerAspectJAnnotationAutoProxyCreatorIfNecessary的源码,第2、3、4步就是向AnnotationAwareAspectJAutoProxyCreator的BeanDefinition设置属性的步骤,看一下第3步和第四步设置proxyTargetClass属性和设置exposeProxy属性,具体看代码块5

代码块3:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
		"org.springframework.aop.config.internalAutoProxyCreator";

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
	//1
	return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
		BeanDefinitionRegistry registry, @Nullable Object source) {
	//2.这里传入AnnotationAwareAspectJAutoProxyCreator.class,也就是将这个类封装成BeanDefinition对象
	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
		Class cls, BeanDefinitionRegistry registry, @Nullable Object source) {	
	//3.判断是否保存了AUTO_PROXY_CREATOR_BEAN_NAME这个BeanDefinition
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		//4.走到这,说明容器中存在这个BeanDefinition,判断从容器中获取的这个BeanClassName和AnnotationAwareAspectJAutoProxyCreator.class
		//这个名称是否相同
		if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
			//5.如果名称不一样,则获取优先级,在这里我们知道cls传过来的是AnnotationAwareAspectJAutoProxyCreator这个类,
			//而这个AnnotationAwareAspectJAutoProxyCreator的优先级是最高的,如果名称不一样,则BeanClassName则会被替换成
			//AnnotationAwareAspectJAutoProxyCreator.class的名称
			int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
			int requiredPriority = findPriorityForClass(cls);
			if (currentPriority < requiredPriority) {
				apcDefinition.setBeanClassName(cls.getName());
			}
		}
		return null;
	}
	//6.走到这,说明容器中没有AUTO_PROXY_CREATOR_BEAN_NAME这个BeanDefinition,下面就是创建这个BeanDefinition
	//然后放到容器中
	RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
	beanDefinition.setSource(source);
	beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
	beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	//7.往容器中注入这个BeanDefinition
	registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
	return beanDefinition;
}

     第3步,判断容器中是否包含封装了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition对象,如果不包含,则直接往容器里面注入一个封装了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition对象,如果包含则判断名称是否相同,如果不相同,获取其优先级,我们知道cls传过来的是AnnotationAwareAspectJAutoProxyCreator这个类,这个类的优先级最高,具体可以看代码块4。对于为什么要封装成BeanDefinition对象,因为在Spring创建bean时,是根据BeanDefinition对象来创建对象的,关于BeanDefinition可以查看:Spring中bean的生命周期(最详细),里面有说到Spring创建bean的大致流程。

代码块4:AopConfigUtils#findPriorityForClass

/**
 * Stores the auto proxy creator classes in escalation order.
 */
private static final List> APC_PRIORITY_LIST = new ArrayList<>(3);

static {
	// Set up the escalation list...
	APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
	APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
	APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}

private static int findPriorityForClass(Class clazz) {
	//1.获取其所在数组的下标值,如果没有这个clazz,则会返回-1
	return APC_PRIORITY_LIST.indexOf(clazz);
}

代码块5:AopConfigUtils#forceAutoProxyCreatorToUseClassProxying

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
    //1.如果容器中包含AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition,则设置proxyTargetClass属性为true,
    //该属性在创建动态代理的时候,会影响使用JDK还是CGLIB来实现动态代理
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
	}
}

public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
	}
}

       如果容器中包含AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition,则设置proxyTargetClass属性为true,该属性在创建动态代理的时候,会影响使用JDK还是CGLIB来实现动态代理,这个到后面再详细说明。

      到此就完成了向Spring容器中注入了一个封装了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition对象,那么这一步什么时候执行呢?我这里大致说一下:

       一: Spring在执行流程中,有一步会执行invokeBeanFactoryPostProcessors,在此步骤会调用所有的BeanFactoryPostProcessors的实现类,也就是在这一步,循环递归的方式,将Spring项目中所有的需要导入的Spring容器的对象封装成BeanDefinition对象,注意,这一步会扫描bean上面的注解,然后进行解析,将AnnotationAwareAspectJAutoProxyCreator封装成BeanDefinition的步骤也会在此随着解析@EnableAspectJAutoProxy而导入到容器中。

Spring AOP源码解析一:AOP代理重要bean---AnnotationAwareAspectJAutoProxyCreator的创建_第1张图片

       上图是AnnotationAwareAspectJAutoProxyCreator的继承关系,可以得知AnnotationAwareAspectJAutoProxyCreator是一个一个bean的后置处理器,而且实现了BeanClassLoaderAware、BeanFactoryAware接口,可以拿到类加载器和bean工厂对象,这个对于后期创建动态代理是很有必要的,而对于bean的后置处理器,可以查看:Spring中bean的生命周期(最详细),这里面会详细的介绍所有的bean的后置处理器的执行时机和作用,会在普通bean实例话之前执行创建bean,会在Spring主流程的registerBeanPostProcessors方法中创建出bean,然后这个BeanPostProcessor会在所有的普通的bean创建时起作用,这样的话,在我们使用了AspectJ注解来完成AOP代理时,在Spring执行流程中AnnotationAwareAspectJAutoProxyCreator这个bean的后置处理器就会起作用。

      关于AnnotationAwareAspectJAutoProxyCreator的创建已经说完了,下篇将介绍普通bean创建时AnnotationAwareAspectJAutoProxyCreator的bean后置处理器起到的作用。

 

你可能感兴趣的:(Spring,spring,Spring,AOP,源码)