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 ...
随机推荐
- 【开源推荐】AI Interviewer:基于Spring-Alibaba-AI的智能面试官系统(附GitHub实战教程)
项目背景 作为开发者,你是否经历过: 技术面试时因紧张发挥失常? 刷了1000+LeetCode却不会表达解题思路? 花费上千元购买模拟面试服务? 今天推荐的AI Interviewer开源项目,正是 ...
- Web前端入门第 32 问:CSS background 元素渐变背景用法全解
渐变背景在 CSS 里面就是一个颜色到另一个颜色渐渐变化的样子. 本文示例中,盒子基础样式: .box { margin: 20px; padding: 20px; border: 10px dash ...
- Condition的await()方法底层源码
一.Condition的await()方法底层源码 以下是 ConditionObject 中 await 方法的源码及其详细分析: public final void await() throws ...
- MySQL 中 varchar 和 char 有什么区别?
MySQL 中 varchar 和 char 的区别 在 MySQL 中,VARCHAR 和 CHAR 是两种常用的字符串类型,它们在存储方式.长度限制和使用场景等方面存在显著区别. 1. 定义与存储 ...
- MySQL 中的数据排序是怎么实现的?
MySQL 中的数据排序实现 在 MySQL 中,数据排序是通过 ORDER BY 子句实现的,主要涉及 文件排序 和 索引排序 两种方式. 1. 排序的基本原理 MySQL 的排序实现分为以下两种情 ...
- Java AI(智能体)编排开发就用 Solon Flow
本例参考 dify 的 chatFlow 的效果,模拟实现视频内容: https://www.toutiao.com/video/7455114080131482152/ Solon Flow 是一个 ...
- xna 渲染3d图片
我们在做一个3d显示的时候为了突出模型的某些部位以及更好的区别某些模块我们需要渲染各种不同的颜色来体现, 下面代码演示: public void loade() { spriteBatch = new ...
- Jeesite5:Star24k,Spring Boot 3.3+Vue3实战开源项目,架构深度拆解!让企业级项目开发效率提升300%的秘密武器
企业级应用开发的需求日益增长.今天,我们要介绍的是一个在GitHub上广受好评的开源项目--Jeesite5.这不仅是一个技术框架,更是企业级应用开发的加速器.接下来,我们将深入探讨Jeesite5的 ...
- HarmonyOS NEXT开发实战教程:聊天交友App
一早醒来Mate70上热搜了,余承东发文宣布Mate70要在本月发布,史上最强手机终于要来了. 今天分享一个交友app实战教程,是幽蓝君用整整一个周末开发的,时间有限,只做了些皮毛,不是很完善,不过拿 ...
- html_py
Sock.py import socket def handle_request(client): buf=client.recv(1024) client.send(bytes(&q ...