文章目录
- 1. Bean的生命周期
- 2. 推断构造方法
- 3. 依赖注入
- 4. 初始化前
- 5. 初始化
- 6. 初始化后
- 7. AOP
- 8. Spring事务
- 9. Spring事务失效
- 10. @Configuration
- 11. 循环依赖
- 12. @Lazy
1. Bean的生命周期
UserService.class --> 推断构造方法 --> 普通对象 --> 依赖注入 --> 初始化前 --> 初始化 --> 初始化后(AOP)--> 代理对象 --> 放入Map(单例池)--> Bean对象
2. 推断构造方法
- 对于bean类中定义了一个构造器(带参数或不带参数),或者不手动定义构造器(此时java默认会隐式的创建一个空参构造器),Spring在创建该bean时使用唯一的构造器。
- 对于bean类中定义了多个构造器,Spring在创建该bean时会默认去找空参构造器,若没有则报错;
- 对于bean类中定义了多个构造器,可以 为指定的构造器添加
@Autowire
注解,此时Spring在创建该bean时会使用指定的构造器。 - 特别的:当Spring使用带参数的构造器创建bean时会在IOC容器中找形参对应的bean(
先类型匹配,再名称匹配
)并传入,找不到或不是bean则会报错
- 对应找到过程,首先如果形参对应的bean是单例的则会先在
单例池
中寻找,找到则传入(先类型匹配,若有多个该类型的bean则再通过名称匹配,此时名称唯一匹配上则注入,没有则报错;若类型匹配只有一个时则直接注入无需匹配名称);若找不到则直接通过反射创建形参对应的bean(可能有多个),将其保存至 单例池
,再查找。(在这个创建过程中可能出现循环依赖问题) - 如果形参对应的bean是多例的,则直接创建一个新的bean实例并注入
@Component
public class UserService{
OrderService orderService;
public UserService(){
}
@Autowire
public UserService(OrderService orderService){
}
}
3. 依赖注入
- 对于bean的类中使用
@Autowire
等注解标注的属性,通过与构造器参数注入相同的方法进行依赖注入 - @Autowire是先按类型匹配,再按名称。只匹配到一个该类型的对象则直接注入,对于匹配到多个该类型的对象再通过名称匹配,有则注入,没有则报错
4. 初始化前
- 执行 @PostConstruct 所标注的方法
- 执行 实现了
BeanPostPocessor 接口
的bean 中的 前置处理方法
5. 初始化
- 若当前创建的 bean 实现了
initializationBean
接口的 afterPropertiesSet
方法,则会执行
6. 初始化后
- 执行 实现了
BeanPostPocessor 接口
的bean 中的 后置处理方法
7. AOP
- Spring的AOP基于Cglib的动态代理实现,其原理如下
8. Spring事务
9. Spring事务失效
- 可以自己注入自己,使用代理对象的a()方法,使得事务生效
10. @Configuration
- 对于自定义的配置类中 @Configuration 为当前配置类对象创建动态代理类(注意:是基于动态代理实现,不是基于AOP实现)其动态代理实现是基于继承
- 由于 Spring 的事务中,需要使
transactionManager
与 jdbcTemplate
均使用一个dataSource(同一个对象),才能使得 ThreadLocal 中的 Map 中顺利传递,以保证事务的顺利执行
class AppConfigProxy extends AppConfig{
public JDBCTemplate jdbcTemplate(){
JDBCTemplate jt = super.jdbcTemplate();
....
}
public DataSource dataSource(){
DataSource ds = super.dataSource()
}
}
@ComponentScan("com.gyh")
@EnableTransactionManagement
@Configuration
public class AppConfig{
@Bean
public JdbcTemplate jdbcTemplate(){
return enw JdbcTemplate(dataSource());
}
@Bean
public PlatformTransactionManager transactionManager(){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource());
}
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("...");
dataSource.setUsername("...");
dataSource.setPassword("...");
return dataSource;
}
}
11. 循环依赖
- 一个循环依赖问题
@Component
public class AService{
@Autowire
private BService bService;
@Autowire
private CService cService;
}
@Component
public class BService{
@Autowire
private AService aService;
}
@Component
public class CService{
@Autowire
private AService aService;
}
- 利用三级缓存解决循环依赖
- 第一级缓存:singletonObjects ---- 在依赖注入时会首先在单例池中查找是否有经完整周期创建的bean,有则直接注入
- 第二级缓存:earlySingletonObjects — 如果单例池中没有则判断是否存在循环依赖,若存在循环依赖,则会在二级缓存中查找是否有还未经完成创建的bean,有则直接获取并注入;没有则进入下一级缓存(二级缓存可以保证多个循环依赖中的单例情况)
- 第三级缓存:singletonFactories — 该缓存会在所有 bean 创建对象(
普通bean对象
)后进行保存,待到某个bean经过二级缓存后需要,则从中寻找该beanName对应的普通对象,若需要提前AOP则进行动态代理,生成该普通对象的代理对象后保存至二级缓存;若没有AOP过程直接将普通bean对象
保存至二级缓存。
12. @Lazy
- 对延迟对指定的属性或构造器参数的注入,在 bean 的属性设置等环节中直接构造它的代理对象并赋值(不执行循环注入逻辑),而在实际使用它的时候再去创建该@Lazy标注的属性或构造器参数的bean二级缓存;若没有AOP过程直接将
普通bean对象
保存至二级缓存。