这篇文章主要是介绍:如何将配置类转换为BeanDefinition的,核心就是:ConfigurationClassPostProcessor
@Configuration、@Import、@ComponentScan的解析是在BeanFactoryPostProcessor的实现类ConfigurationClassPostProcessor中完成的,解析结果会被注册为BeanDefinition
- 02-Java13
- 03-多线程12
- 01-笔试常见题10
- 11-SpringCloud10
- 10-SpringBoot9
- 12-MQ9
- 05-Mysql8
- 09-Mybatis8
- 15-设计模式8
- 04-Jvm7
- 06-Redis7
- 08-Spring7
- 工具7
- 14-Zookeeper6
- Netty5
- 工作流5
- 07-SpringMvc4
- 13-Dubbo4
- Docker3
- Nginx2
2026/9/27大约 30 分钟
三级缓存存放的是什么:
- 一级缓存:成品对象
- 二级缓存:半成品对象
- 三级缓存:lamda表达式,放入的函数是:
getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean)参数bean是方法doCreateBean方法通过反射实例化的对象。
演练一下循环依赖的执行流程:
| 时间点 | A 的状态 | B 的状态 | 关键动作 |
|---|---|---|---|
| 1. 实例化 A | A_raw 生成 | 未创建 | 调用 A 的构造方法。此时不生成代理。 |
| 2. A 放入三级缓存 | A_raw 存在 | 未创建 | 存入 Lambda:() -> getEarlyBeanReference(A)。此时仍不生成代理。 |
| 3. 填充 A 的属性 | A_raw 存在 | 未创建 | 发现依赖 B,暂停 A 的创建,转去创建 B。 |
| 4. 实例化 B | A_raw 存在 | B_raw 生成 | 调用 B 的构造方法。 |
| 5. B 放入三级缓存 | A_raw 存在 | B_raw 存在 | 存入 Lambda:() -> getEarlyBeanReference(B)。 |
| 6. 填充 B 的属性 | A_raw 存在 | B_raw 存在 | 发现依赖 A,调用 getBean(A)。 |
| 7. B 获取 A 的代理 | A_proxy 生成 | B_raw 存在 | 从三级缓存执行 Lambda,A 的代理在此刻生成,放入二级缓存。B_raw 拿到 A_proxy。 |
| 8. B 的属性填充完成 | A_proxy 存在 | B_raw 持有 A_proxy | B 的其他属性注入完成。 |
| 9. B 初始化 | A_proxy 存在 | B_raw 初始化 | 执行 B 的 @PostConstruct、afterPropertiesSet 等。 |
| 10. B 生成最终代理 | A_proxy 存在 | B_proxy 生成 | 经过 BeanPostProcessor,B 的代理在此刻生成,放入一级缓存。 |
| 11. 回到 A 的填充 | A_raw 获取 B_proxy | B_proxy 已存在 | A 的依赖 B 注入完成(拿到 B_proxy)。 |
| 12. A 初始化 | A_raw 初始化 | B_proxy 已存在 | 执行 A 的 @PostConstruct 等。 |
| 13. A 的代理替换 | A_proxy 替代 A_raw | B_proxy 已存在 | Spring 检查二级缓存有 A_proxy,用其替换 A_raw,放入一级缓存。 |
| 14. 最终容器 | A_proxy | B_proxy | 两个代理对象都存在于一级缓存。 |
| 11到13步的处理中“替换”这个概念你可能会有这样的疑问 11.A_raw 获取 B_proxy,二级缓存中的 A_proxy又没获取B_proxy,直接用二级缓存中的 A_proxy代替A_raw,二级缓存中的 A_proxy的属性B不是null的吗? | |||
| 错误的理解(你以为的): |
2026/9/27大约 17 分钟
一,Spring AOP 配置使用
目前 Spring AOP 一共有三种配置方式,Spring 做到了很好地向下兼容,所以大家可以放心使用。
- Spring 1.2 基于接口的配置:最早的 Spring AOP 是完全基于几个接口的,想看源码的同学可以从这里起步。
- Spring 2.0 schema-based 配置:Spring 2.0 以后使用 XML 的方式来配置,使用 命名空间
- Spring 2.0 @AspectJ 配置:使用注解的方式来配置,这种方式感觉是最方便的,还有,这里虽然叫 做 @AspectJ,但是这个和 AspectJ 其实没啥关系。
2026/9/27大约 26 分钟
解析切面,创建代理
一,spring事务源码解析
// 1,关闭mysql的自动提交事务
try{
// 原方法
}catch (Throwable var20) {
// 2,事务回滚
} finally {
// 清空
}
// 3,事务提交
2026/9/27大约 25 分钟
一、@Conditional
@Conditional来源于spring-context包下的一个注解。Conditional中文是条件的意思,@Conditional注解它的作用是按照一定的条件进行判断,满足条件给容器注册bean:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
2026/9/27大约 3 分钟
一、快速开始
第一步:导入jar
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2026/9/27大约 6 分钟
spring事务的实现原理
- 1,解析切面:BeanFactoryPostProcess中执行解析。@EnableTransactionmanagement注解注册了一个配置类,配置类引入了adivsor。
- 2,创建动态代理:初始之后Bean的后置处理器。有接口使用JDK动态代理,没接口使用CGLIB动态代理。创建动态代理之前,需要先判断是否需要创建代理,是根据pointcut匹配的。判读方法上,类上,接口的方法上。
- 3,执行:
FactoryBean和BeanFactory的区别
FactoryBean的GetObject方法调用时机是:FactoryBean发生在属性填充(依赖注入)之后,FactoryBean但在初始化方法(@PostConstruct / InitializingBean)之前。所以FactoryBean的getObject() 方法返回的对象的实例化,对象的属性填充 需要自己在getObject() 方法中完成。而FactoryBean的自己的实例化和属性填充是正常的Bean。FactoryBean的getObject() 方法是不是相当于在容器中注册了2个Bean,一个FactoryBean对象,一个getObject() 方法返回的对象,但实际上,注册表(BeanDefinitionRegistry)中只有 FactoryBean 的 BeanDefinition,getObject() 返回的对象不会生成 BeanDefinition,它是在运行时通过 getObject() 动态创建并缓存在容器中的。
2026/9/27大约 7 分钟