粗浅分析注解spring AOP源码--------(一)

9 篇文章 0 订阅
5 篇文章 0 订阅

这次来浅谈一下注解spring AOP 的源码,在spring底层代码中,作为开启注解AOP的 @EnableAspectJAutoProxy 究竟干了些啥。
本文章记录的是博主学习aop源码的一些理解,如果有错,望指出

1. 是个啥?

它,长这样:
@EnableAspectJAutoProxy
这里重点是 @Import(AspectJAutoProxyRegistrar.class),导入了 AspectJAutoProxyRegistrar.class

AspectJAutoProxyRegistrar类

进入这个类中,在注释中发现这个类是用来将 AnnotationAwareAspectJAutoProxyCreator 这个类注册到 BeanDefinitionRegistry 里。
AspectJAutoProxyRegistrar
AnnotationAwareAspectJAutoProxyCreator 这个类是什么呢?这里先不说,在后面更新的文章中会详细讲解。

那么,这个类要怎么把 AnnotationAwareAspectJAutoProxyCreator 这个类注册到 BeanDefinitionRegistry 里的呢?

继续往下看,可以看到该类中重写了一个方法:
registerBeanDefinitions
这里关注一下圈起来的代码,这个代码的意思大概是“如果需要的话就注册AspectJAnnotationAutoProxy的创造者”。点进去之后会发现方法内又调用了与该方法重名的另一个方法:
registerAspectJAnnotationAutoProxyCreatorIfNecessary
圈起来的代码的大意是“注册或升级xxx(我也不懂)”,然后传入了上面提到的 AnnotationAwareAspectJAutoProxyCreator.class,此时继续进去看看发生了什么。

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

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

/** 直接看这里
 这里是判断bean的定义工厂registry中有没有
AUTO_PROXY_CREATOR_BEAN_NAME ="org.springframework.aop.config.internalAutoProxyCreator"
 第一次运行项目时是没有的,结果为 false
*/
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;
	}
/**
此时代码执行到这里;
下方的代码都是在向bean定义工厂中注册 
AnnotationAwareAspectJAutoProxyCreator,并且该类的名称设置为
org.springframework.aop.config.internalAutoProxyCreator,

由此:internalAutoProxyCreator = AnnotationAwareAspectJAutoProxyCreato
*/
		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;
	}

代码执行完之后,registry 中已经存在了 AnnotationAwareAspectJAutoProxyCreator 的定义。

注意:这时,AnnotationAwareAspectJAutoProxyCreator 只是在bean工厂中定义了,还没有创建对象。在这里插入图片描述
到此,@EnableAspectJAutoProxy 做了一件事,将 AnnotationAwareAspectJAutoProxyCreator 定义到了bean的工厂中(尚未创建对象)

2.AnnotationAwareAspectJAutoProxyCreator

分析继承关系如下

AnnotationAwareAspectJAutoProxyCreator
    -> AspectJAwareAdvisorAutoProxyCreator
      -> AbstractAdvisorAutoProxyCreator
       -> AbstractAutoProxyCreato extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor,  BeanFactoryAware 

其中
	ProxyProcessorSupport
		-> extends ProxyConfig
           implements Ordered, BeanClassLoaderAware, AopInfrastructureBean
    SmartInstantiationAwareBeanPostProcesso
        ->InstantiationAwareBeanPostProcessor
               -> BeanPostProcessor        
    BeanFactoryAware
        ->Aware
    BeanClassLoaderAware        
        ->Aware

在这些类中需要关注 3 个方法:
AbstractAutoProxyCreato.postProcessAfterInitializationj()
AbstractAutoProxyCreato.postProcessBeforeInstantiation()
AbstractAdvisorAutoProxyCreator.setBeanFactory()

这三个方法可以让我们在理解AOP代码的过程中起到很大的作用。

创建和注册

先定义一个增强类和被增强类并注入到IOC容器中,并打上断点

/**
 * 告诉spring这个类是切面类(增强类)
 */
@Aspect
public class LogAspect {

    /**
     抽取切入点表达式
     *
     */
    @Pointcut("execution(* aopEntity.PlayGame.*(..))")
    public void pointcut(){}

    /**
     *
     前置通知
     */
    @Before(value = "pointcut()")
    public void logStart(){
        System.out.println("前置通知执行。。。");
    }

    @After(value = "pointcut()")
    public void logAfter(){
        System.out.println("后置通知执行。。。");
    }

    @AfterReturning(value="pointcut()")
    public void logReturning(){
        System.out.println("返回通知执行。。。");
    }

    @AfterThrowing(value = "pointcut()")
    public void logThrowing(){
        System.out.println("异常通知执行。。。");
    }

}

/**
     被增强类
*/
public class PlayGame {

    public void play(){
        System.out.println("开始play。。。");
    }
}


/**
 * 开启基于注解的aop功能
 */
@EnableAspectJAutoProxy
@Configuration
public class AopConfig {

    /**
     * 将业务逻辑类加载到容器中
     * 打上断点
     * @return
     */
    @Bean
    public PlayGame playGame(){
        return new PlayGame();
    }

    /**
     * 将切面类加载到容器中
     * 打上断点
     */
    @Bean
    public LogAspect logAspect(){
        return new LogAspect();
    }
}


步骤:
1、传入配置类,调用 refresh() 刷新容器
2、 调用 registerBeanPostProcessors(beanFactory) :注册拦截Bean创建的Bean处理器
3、 调用PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
4、 获取所有已经定义了需要获取对象的所有BeanPostProcessor

获取所有的bean后置处理器
5、 分别给容器中添加实现了PriorityOrdered接口、Ordered接口、没实现以上接口的BeanPostProcessor
6、 注册实现Ordered接口的internalAutoProxyCreator(实际上就是AnnotationAwareAspectJAutoProxyCreator) ,。AnnotationAwareAspectJAutoProxyCreator 已经实现了Ordered 接口
在这里插入图片描述
getBean()调用流程:getBean()->doGetBean()->getSingleton()
6.1 、先给Bean赋值(populateBean()方法),然后创建并初始化bean实例
在这里插入图片描述
6.2、 执行Aware接口中的被实现的setBeanFactory()
在这里插入图片描述
6.3、 执行applyBeanPostProcessorsBeforeInitialization()。获取所有的后置处理器,调用每个后置处理器中的postProcessBeforeInitialization()

在这里插入图片描述
在这里插入图片描述
6.4、 执行自定义的初始化方法
在这里插入图片描述
6.5、 执行applyBeanPostProcessorsAfterInitialization。获取所有的后置处理器,调用每个后置处理器中的postProcessAfterInitialization()
在这里插入图片描述
在这里插入图片描述
7、 完成internalAutoProxyCreator(实际上就是AnnotationAwareAspectJAutoProxyCreator) 的初始化操作

8、 初始化BeanFactory,到此,AnnotationAwareAspectJAutoProxyCreator 创建成功。
在这里插入图片描述
8、 添加到已创建的bean的集合中。
在这里插入图片描述

9、 对beanPostProcessors进行排序和注册

在这里插入图片描述

到此,**AnnotationAwareAspectJAutoProxyCreator **创建注册完成。

粗浅分析注解spring AOP源码--------(二)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值