1.Java Spring框架源码分析-AOP-给容器中注入AspectJAnnotationAutoProxyCreator组件
一般我们开启aop的功能是通过@EnableAspectJAutoProxy,所以首先查看其源码
1. 开启AOP
- @EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)//给容器中导入AspectJAutoProxyRegistrar组件
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
关键在于导入的AspectJAutoProxyRegistrar这个类,他想容器中注入了一些组件
2. 注册AspectJAnnotationAutoProxyCreator组件
- AspectJAutoProxyRegistrar registerBeanDefinitions
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {//继承了ImportBeanDefinitionRegistrar
//重写的这个方法可以先容器中注入bean的class
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//这里打一个断点
//这个名字的意思是如果需要的话注入AspectJAnnotationAutoProxyCreator这个bean的class
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
//从EnableAspectJAutoProxyv中获取proxyTargetClass和exposeProxy进行处理
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
- AopConfigUtils registerAspectJAnnotationAutoProxyCreatorIfNecessary
public abstract class AopConfigUtils {
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//是否已经注册了org.springframework.aop.config.internalAutoProxyCreator
//没有的话走30行
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;
}
//将org.springframework.aop.config.internalAutoProxyCreator:AnnotationAwareAspectJAutoProxyCreator.class
//注册进容器中
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;
}
}
3. ImportBeanDefinitionRegistrar的registerBeanDefinitions是什么步骤被调用的
在这个方法上打个断点,调试调用栈如下:
registerBeanDefinitions:45, AspectJAutoProxyRegistrar (org.springframework.context.annotation)
loadBeanDefinitionsFromRegistrars:360, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
loadBeanDefinitionsForConfigurationClass:144, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
loadBeanDefinitions:116, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
processConfigBeanDefinitions:320, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (org.springframework.context.support)
refresh:524, AbstractApplicationContext (org.springframework.context.support)
<init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:26, AopConfig
参考2.调用BeanFactoryPostProcessor的postProcess方法.md 先调用PriorityOrdered类型的postProcessBeanDefinitionRegistry方法
可以发现调用的是ConfigurationClassProprocessor的postProcessBeanDefinitionRegistry方法

3.1. 跟踪ConfigurationClassProprocessor的postProcessBeanDefinitionRegistry方法
- ConfigurationClassProprocessor postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//...
processConfigBeanDefinitions(registry);//这里
}
- ConfigurationClassProprocessor processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//...
//这里configClasses包含了我们自己的AopCofig这个@Configuration
this.reader.loadBeanDefinitions(configClasses);
//...
}

接着就是
- ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);//这里
}
}
- ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
//...
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

- ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
}
}

最后调用到了AspectJAutoProxyRegistrar#registerBeanDefinitions
1.Java Spring框架源码分析-AOP-给容器中注入AspectJAnnotationAutoProxyCreator组件的更多相关文章
- Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理
Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...
- Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析
Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...
- 设计模式(五)——原型模式(加Spring框架源码分析)
原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...
- 干货分享之spring框架源码分析02-(对象创建or生命周期)
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 之前分析了Spring读取xml文件的所有信息封装成beanDef ...
- Java集合框架源码分析(2)LinkedList
链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...
- 细说并发5:Java 阻塞队列源码分析(下)
上一篇 细说并发4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文 ...
- Spring Ioc源码分析系列--Bean实例化过程(一)
Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- 精尽Spring Boot源码分析 - 剖析 @SpringBootApplication 注解
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- Spring Ioc源码分析系列--Ioc的基础知识准备
Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...
随机推荐
- Windows 系统授权服务信息
cmd 中输入命令 slmgr.vbs /dlv 后查看输出信息 据说,OEM和RETAIL可以正常升级到Windows10,并永久激活
- javascript 数值交换技巧
需求 现在存在var a = 1,b = 2;,要求使用javascript实现a & b数值的交换,让a = 2,b = 1. 中间变量(常规实现方式) var a = 1, b = 2; ...
- leetcode每日一题:k-avoiding 数组的最小总和
引言 今天是本次开始坚持leetcode每日1题的第10天,也算是迈出了一小步. 题目 2829. k-avoiding 数组的最小总和 给你两个整数 n 和 k . 对于一个由 不同 正整数组成 ...
- 洛谷P4198 楼房重建 题解
Part1.自己一开始是怎么想的 我一开始的想法是先考虑什么情况下是看不见的. 如果是 \(i < j\) 的话可以直接看 \(j\) 的斜率和 \(i\) 的斜率就是比较 \(\frac{h_ ...
- ESP32S3播放音频文件
ESP32S3播放音频文件 硬件基于立创实战派esp32s3 软件代码基于立创实战派教程修改,分析 播放PCM格式音频 原理图分析 音频芯片ES8311 ES8311_I2C_ADD:0x18 音频功 ...
- iOS深色模式媒体查询css
@media (prefers-color-scheme: dark) { body { background-color: #000; color: #fff; } }
- 搞定 XLSX 预览?别瞎找了,这几个库(尤其最后一个)真香!
- Hey, 我是 沉浸式趣谈 - 本文首发于[沉浸式趣谈],我的个人博客 **https://yaolifeng.com** 也同步更新. - 转载请在文章开头注明出处和版权信息. - ...
- Harmony 动态路由框架:TheRouter 开源
TheRouter 是一个用于移动端APP,包括 Android.iOS.Harmony 三端的模块化.组件化开发的一整套解决方案框架.提供了三端高一致性,对移动端开发者更友好,让开发人员更适应,使用 ...
- Burp插件Fiora联动nuclei(windows)
大佬写的插件出来好久了 今天朋友问我Fiora联动nuclei,我突然忘了咋配的的了.. 记录一下 一.下载nuclei https://github.com/projectdiscovery/nuc ...
- 2.7K star!这个汉字工具库让中文处理变得超简单,开发者必备!
嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 cnchar 是一个功能全面的汉字工具库,提供拼音转换.笔画动画.偏旁查询.成语接龙.语音合 ...