AOP原理 - 分析@EnableAspectJAutoProxy注解源码

一、@EnableAspectJAutoProxy注解说明

在配置类上添加@EnableAspectJAutoProxy注解,能够开启注解版的AOP功能。也就是说,AOP中如果要使用注解版的AOP功能起作用,就需要在配置类上添加@EnableAspectJAutoProxy注解。 我们先来看下@EnableAspectJAutoProxy注解的源码,如下所示:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	 boolean proxyTargetClass() default false;
	 boolean exposeProxy() default false;
}

从源码可以看出,@EnableAspectJAutoProxy使用@Import注解引入了AspectJAutoProxyRegister.class对象 。那么,AspectJAutoProxyRegistrar又是什么呢?我们继续点击到AspectJAutoProxyRegistrar类的源码中,如下所示:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	 @Override
	 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	
		  AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		
		  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接口。看下ImportBeanDefinitionRegistrar接口的定义,如下所示:

public interface ImportBeanDefinitionRegistrar {

	 default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
	   BeanNameGenerator importBeanNameGenerator) {
	
	  	registerBeanDefinitions(importingClassMetadata, registry);
	 }
	
	 default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	 }
}

ImportBeanDefinitionRegistrar接口功能:可以通过ImportBeanDefinitionRegistrar接口实现将自定义的组件添加到IOC容器中。

也就说,@EnableAspectJAutoProxy注解使用AspectJAutoProxyRegistrar对象自定义组件,并将相应的组件添加到IOC容器中。

二、调试@EnableAspectJAutoProxy源码

在AspectJAutoProxyRegistrar类的registerBeanDefinitions()方法中设置断点,如下所示:

在这里插入图片描述

接下来,我们以debug的方法来运行AopTest类的testAop01()方法。运行后程序进入到断点位置,如下所示:

在这里插入图片描述

可以看到,程序已经暂停在断点位置,而且在IDEA的左下角显示了方法的调用栈。

在AspectJAutoProxyRegistrar类的registerBeanDefinitions()方法,首先调用AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法来注册registry。单看registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法也不难理解,字面含义就是:如果需要的话注册一个AspectJAnnotationAutoProxyCreator。

接下来,我们进入到AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,如下所示:

在这里插入图片描述

在AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,直接调用了重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法,我们继续跟代码,如下所示:

在这里插入图片描述

可以看到在重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中直接调用了registerOrEscalateApcAsRequired()方法。在registerOrEscalateApcAsRequired()方法中,传入了AnnotationAwareAspectJAutoProxyCreator.class对象。

我们继续跟进代码,如下所示:

在这里插入图片描述

我们可以看到,在registerOrEscalateApcAsRequired()方法中,接收到的Class对象的类型为:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator。

在registerOrEscalateApcAsRequired()方法中方法中,首先判断registry是否包含org.springframework.aop.config.internalAutoProxyCreator类型的bean。如下所示:

在这里插入图片描述

如果registry中包含org.springframework.aop.config.internalAutoProxyCreator类型的bean,则进行相应的处理,从Spring的源码来看,就是将org.springframework.aop.config.internalAutoProxyCreator类型的bean从registry中取出,并且判断cls对象的name值和apcDefinition的beanClassName值是否相等。如果不相等,则获取apcDefinition和cls的优先级,如果apcDefinition的优先级小于cls的优先级,则将apcDefinition的beanClassName设置为cls的name值。相对来说,理解起来还是比较简单的。

我们这里是第一次运行程序,不会进入到 if 条件中,我们继续看代码,如下所示:

在这里插入图片描述

这里,使用RootBeanDefinition来创建一个beanDefinition,并且将org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator的Class对象作为参数传递进来。

在这里插入图片描述

我们继续往下看代码,最终AopConfigUtils类的registerOrEscalateApcAsRequired()方法中,会通过registry调用registerBeanDefinition()方法注册组件,如下所示:

在这里插入图片描述

并且注册的bean的名称为org.springframework.aop.config.internalAutoProxyCreator。

接下来,我们继续看AspectJAutoProxyRegistrar类的registerBeanDefinitions()源码,如下所示:

在这里插入图片描述

通过AnnotationConfigUtils类的attributesFor方法来获取@EnableAspectJAutoProxy注解的信息。接下来,就是判断proxyTargetClass属性的值是否为true,如果为true则调用AopConfigUtils类的forceAutoProxyCreatorToUseClassProxying()方法;继续判断exposeProxy属性的值是否为true,如果为true则调用AopConfigUtils类的forceAutoProxyCreatorToExposeProxy()方法。

综上,向Spring的配置类上添加@EnableAspectJAutoProxy注解后,会向IOC容器中注册AnnotationAwareAspectJAutoProxyCreator。

接下来,我们来看下AnnotationAwareAspectJAutoProxyCreator类的结构图

在这里插入图片描述

我们简单梳理下AnnotationAwareAspectJAutoProxyCreato类的核心继承关系,如下所示:
AnnotationAwareAspectJAutoProxyCreator
->AspectJAwareAdvisorAutoProxyCreator(父类)
->AbstractAdvisorAutoProxyCreator(父类)
->AbstractAutoProxyCreator(父类)
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware(两个接口)

查看继承关系可以发现,此类实现了Aware与BeanPostProcessor接口,这两个接口都和Spring bean的初始化有关,由此推测此类主要处理方法都来自这两个接口的实现方法。同时该类也实现了order方法。

有关AnnotationAwareAspectJAutoProxyCreator类的详细代码和执行流程下一章讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值