一般我们开启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组件的更多相关文章

  1. Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理

    Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...

  2. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  3. 设计模式(五)——原型模式(加Spring框架源码分析)

    原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...

  4. 干货分享之spring框架源码分析02-(对象创建or生命周期)

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 之前分析了Spring读取xml文件的所有信息封装成beanDef ...

  5. Java集合框架源码分析(2)LinkedList

    链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...

  6. 细说并发5:Java 阻塞队列源码分析(下)

    上一篇 细说并发4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文 ...

  7. Spring Ioc源码分析系列--Bean实例化过程(一)

    Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...

  8. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  9. 精尽Spring Boot源码分析 - 剖析 @SpringBootApplication 注解

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  10. Spring Ioc源码分析系列--Ioc的基础知识准备

    Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...

随机推荐

  1. 【Yuexingfei_qwq的原创游戏】

    好的其实标题里的Yuexingfei_qwq指的是我. 不定时持续更新ing-- 有bug及时回复或私信我哈-- 本文同步发表在以下Blog: 洛谷:https://www.luogu.com.cn/ ...

  2. 7. RabbitMQ 消息队列——延时队列(Spring Boot + 安装message_exchange"延迟插件" 的详细配置说明)的详细讲解

    7. RabbitMQ 消息队列--延时队列(Spring Boot + 安装message_exchange"延迟插件" 的详细配置说明)的详细讲解 @ 目录 7. Rabbit ...

  3. Codeforces Round 970 (Div. 3)

    A. Sakurako's Exam 分类讨论即可,当a为奇数,无法消去1,或者a==0且b为奇数时,无法消去2 #include <bits/stdc++.h> using namesp ...

  4. Eclipse java项目转Maven项目

    1.右键项目->configure->选择maven->配置maven的pom.xml 2.在src/main下新建java文件,将原来src下的java文件夹拷贝至该目录下: 3. ...

  5. Asp.net mvc基础(十三)集合常用的扩展方法和Linq语句

    详情参考:C#之集合常用扩展方法与Linq - 冯继强fjq - 博客园 (cnblogs.com)

  6. ThinkPHP 中闭包在数组查询条件中的深度应用

    一.闭包与数组条件的协同原理 在 ThinkPHP 的查询体系中,数组条件是构建查询逻辑的核心载体.当数组条件的值为闭包(Closure)时,框架会自动将其解析为动态子查询生成器,实现运行时按需构建 ...

  7. 【记录】Python3|用百度语音 API 朗读你的小说TXT

    百度语音合成官方教程_AI开放平台 百度语音合成官方demo_github.com 简单地写了一个按段落朗读文本的demo:DEMO链接_gitee.com. 有时候会请求不到数据,不知道是网络原因还 ...

  8. 超越代码生成:AI 如何重塑软件开发全生命周期 (SDLC)? (需求、测试到部署)

    引言:AI 不止写代码,软件开发的"全链路"变革已至 各位技术圈的朋友们,提到 AI 在软件开发中的应用,恐怕大多数人首先想到的还是 GitHub Copilot.DeepSeek ...

  9. 信息资源管理综合题之“如何利用PKI实现身份认证和抗抵赖和防篡改等安全措施 ”

    一.A企业在网上招标采购某种原材料,B是某个参与招标供应商 1.请讨论如何利用PKI(公钥基础设施),实现A企业接收B报价过程的身份认证.抗抵赖和防篡改等安全措施 二.答案 1.请讨论如何利用PKI( ...

  10. 2025第一届轩辕杯Misc详解

    Terminal Hacker 一步到位 flag{Cysay_terminal_game_hacked_successfully} 哇哇哇瓦 foremost分离 GekkoYoru 随波逐流检测, ...