代碼塊
一 概述
xml時代,Spring Bean是通過ClassPathXmlApplicationContext創(chuàng)建管理的. 而后,新版SpringMVC和Spring Boot 替換為AnnotationConfigApplicationContext,支持注解的方式創(chuàng)建Bean. 實例代碼:
@ComponentScan("com.zhouyu")
public class AppConfig {
@Bean
public UserService userService(){
return new UserService();
}
}
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
二 掃描所有需要創(chuàng)建的Bean
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
- 解析AppConfig.class, 獲取ComponentScan注解定義的包路徑.
- 獲取包路徑下所有class,查看是否有@Component嚼鹉、 @Service等注解. 如果有,則保存下來Map<String, Class> --BeanDefinitionMap, key:按規(guī)則生成的beanName,value就是類本身
三 Bean創(chuàng)建
context.getBean("userService")
3.1 利用構造方法實例化對象
- 通過beanName, 從BeanDefinitionMap中,獲取到要創(chuàng)建對象的class類
- 調(diào)用class類的構造方法實例化一個對象
推斷構造方法
推斷構造方法:存在多個構造方法,如何進行選擇
- 如果只有一個,直接使用它
- 如果大于一個,其中存在無參構造方法,調(diào)用無參構造方法
- 如果大于一個,且不存在無參構造方法,但是某個存在注解@Autowired,則使用@Autowired注解這個
- 如果大于一個,且不存在無參構造方法, 所有構造方法都沒有使用@Autowired,則報錯
3.2 屬性注入
獲取類的所有屬性,檢查是否包含@Autowired,@Resource等注解的屬性.存在則Spring找到并注入(依賴注入). 這里可能存在循環(huán)依賴.
3.3 Aware接口回調(diào)
通過檢查實例化對象是否實現(xiàn)了XXXAware接口, 容器在屬性注入后,回調(diào)接口方法,傳入Bean創(chuàng)建時候的環(huán)境信息給Bean
BeanNameAware: 傳遞beanName
BeanClassLoaderAware: 傳遞類加載器
BeanFactoryAware:傳遞beanFactory
...
3.4 初始化前置調(diào)用
Spring會判斷該對象中是否存在某個方法被@PostConstruct注解 了锅知,如果存在,Spring會調(diào)用當前對象的此方法
3.5 初始化調(diào)用
Spring會判斷該對象是否實現(xiàn)了InitializingBean接口听盖,如果實現(xiàn)了朦前,就表示當前對象必須實現(xiàn)該接口中的afterPropertiesSet()方法,那Spring就會調(diào)用當
前對象中的afterPropertiesSet()方法
3.6 初始化后置調(diào)用
Spring會判斷當前對象需不需要進行AOP,如果不需要那么Bean就創(chuàng)建完 了褥符,如果需要進行AOP龙誊,則會進行動態(tài)代理并生成一個代理對象做為Bean
當Spring根據(jù)UserService類來創(chuàng)建一個Bean時:
- 如果不用進行AOP,那么Bean就是UserService類的構造方法所得到的對象喷楣。
- 如果需要進行AOP趟大,那么Bean就是UserService的代理類所實例化得到的對象鹤树,而不是UserService本身所得到的對象。
四 單例與原型
通過@Scope注解. 判斷對象時 單例還是原型.
- 如果是單例, 則將對象放入單例池(Map<String,Object> ),返回
- 如果是原型,則直接返回
五. AOP擴展
5.1 AOP大致流程
1) 判斷是否需要AOP
a. 獲取所有的切面Bean
b. 遍歷所有方法, 是否@Before逊朽、@After等注解
c. 如果有,則判斷所對應的Pointcut是否和當前Bean對象的類是否匹配
d. 如果匹配到,表示需要AOP
2) cglib進行AOP的大致流程
a. 生成代理類UserServiceProxy罕伯,代理類繼承UserService
b. UserServiceProxy 重寫UserService中方法(test),且持有元UserService對象(target)
c. 重寫代碼
執(zhí)行切面邏輯(@Before)
調(diào)用target.test()
執(zhí)行切面邏輯(@after)
5.2 Spring 事務大致流程
Spring事務也是通過AOP實現(xiàn)的
大致流程如下:
a. 判斷當前執(zhí)行的方法是否存在@Transactional注解
b. 如果存在,則利用事務管理器(TransactionMananger)新建一個數(shù)據(jù)庫連接
c. 修改數(shù)據(jù)庫連接的autocommit為false
d. 執(zhí)行業(yè)務代碼即執(zhí)行sql
e. 執(zhí)行完了之后如果沒有出現(xiàn)異常叽讳,則提交追他,否則回滾
大坑
Spring事務是否會失效的判斷標準:某個加了@Transactional注解的方法被調(diào)用時,要判斷到底是不是直接被代理對象調(diào)用的岛蚤,如果是則事務會生效邑狸,如果不是則失效。 當然,所有AOP實現(xiàn)都是如此.