文章目录 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实例并注入
java">@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 中顺利传递,以保证事务的顺利执行
java">class AppConfigProxy extends AppConfig { public JDBCTemplate jdbcTemplate ( ) { JDBCTemplate jt = super . jdbcTemplate ( ) ; . . . . } public DataSource dataSource ( ) { DataSource ds = super . dataSource ( ) }
}
java">
@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. 循环依赖
一个循环依赖问题
java">
@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对象
保存至二级缓存。