深入探究Spring底層核心原理
Spring底層核心原理
下面這幾行代碼是一個(gè)Spring的入門(mén)代碼,第一行是通過(guò)java配置類(lèi) 注解的方式創(chuàng)建一個(gè)Spring容器,第二行是通過(guò)XML配置文件的方式創(chuàng)建一個(gè)Spring容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test();
最后兩行代碼就是從Spring容器中拿一個(gè)Bean對(duì)象并執(zhí)行方法。那么Spring是如何創(chuàng)建一個(gè)Bean對(duì)象的嘞?
Bean的生命周期
- 推斷構(gòu)造方法,并執(zhí)行得到普通對(duì)象
- 依賴注入
- aware回調(diào)
- 初始化前
執(zhí)行BeanPostProcessor接口中的postProcessBeforeInitialization()方法
- 初始化
執(zhí)行有@PostConstruct注解的方法執(zhí)行
InitializingBean接口中的afterPropertiesSet()方法
執(zhí)行XML配置文件中init-method屬性指定的方法
- 初始化后
執(zhí)行BeanPostProcessor接口中的postProcessAfterInitialization()方法
- 普通對(duì)象/代理對(duì)象 存入容器中
- 使用
- 銷(xiāo)毀
執(zhí)行DisposableBean接口的destroy()方法
有@PreDestroy注解的方法
XML 配置文件中destroy-method屬性指定的方法
推斷構(gòu)造方法
如果沒(méi)有寫(xiě)構(gòu)造方法,那么Spring會(huì)執(zhí)行默認(rèn)空參的構(gòu)造方法
如果顯示寫(xiě)了一個(gè)構(gòu)造方法,那么Spring就會(huì)使用這個(gè)構(gòu)造方法,構(gòu)造方法中如果有參數(shù)那么會(huì)進(jìn)行依賴注入
如果顯示寫(xiě)了多個(gè)構(gòu)造方法并有空參的構(gòu)造方法時(shí),會(huì)執(zhí)行空參的構(gòu)造方法
如果顯示寫(xiě)了多個(gè)構(gòu)造方法沒(méi)有空參的構(gòu)造方法時(shí),運(yùn)行時(shí)會(huì)報(bào)錯(cuò)。解決方法是在要執(zhí)行的構(gòu)造方法上加@Autowired注解
AOP原理
cjlib和jdk兩種動(dòng)態(tài)代理的實(shí)現(xiàn)都是有一個(gè)target屬性來(lái)存儲(chǔ)普通對(duì)象,代理對(duì)象中重寫(xiě)要執(zhí)行的方法,首先執(zhí)行增強(qiáng)邏輯,然后通過(guò)target屬性去執(zhí)行目標(biāo)方法。偽代碼如下:
public class UserServiceProxy extends UserService{
private UserService target;
public void test(){
// TODO 增強(qiáng)業(yè)務(wù)
target.test();
// TODO 增強(qiáng)業(yè)務(wù)
}
}
那么如何判斷一個(gè)Bean是否需要進(jìn)行AOP創(chuàng)建一個(gè)普通對(duì)象嘞?
- 遍歷所有有
@Aspect注解的切面Bean - 遍歷所有的方法
- 判斷方法上的切點(diǎn)表達(dá)式是否和當(dāng)前正在創(chuàng)建的Bean匹配
- 如果匹配則把這個(gè)切面中增強(qiáng)方法存入一個(gè)Map緩存中
真正要執(zhí)行代理對(duì)象的方法時(shí)會(huì)從緩存中取出相應(yīng)的增強(qiáng)邏輯來(lái)執(zhí)行,再去執(zhí)行目標(biāo)方法。
Spring事務(wù)
Spring中如果要使用事務(wù)需要配置一個(gè)JdbcTemplate和一個(gè)事務(wù)管理器,它們倆都需要配置DataSource。
@ComponentScan("com.hs")
@Configuration
public class AppConfig {
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource());
return transactionManager;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/hs?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
}
Spring事務(wù)大致執(zhí)行流程如下:
- 判斷要執(zhí)行的方法上是否存在
@Transcational注解 - 如果存在則通過(guò)事務(wù)管理器創(chuàng)建一個(gè)connection連接對(duì)象
- autoCommit設(shè)置為false
- 去執(zhí)行目標(biāo)方法target.method()
- 如果出現(xiàn)了異常則回滾rollback(),沒(méi)有異常則提交commit()
如果上面的配置類(lèi)中不加@Configuration注解,那么Spring的事務(wù)會(huì)失效。原因如下:
JdbcTemplate和事務(wù)管理器都需要DataSource,都會(huì)調(diào)用dataSource()獲取。如果不加@Configuration注解,那么他們倆獲取的DataSource就不是同一個(gè)。
代理對(duì)象中操作的是事務(wù)管理器的連接對(duì)象,而業(yè)務(wù)方法卻是使用的JdbcTemplate,所以就導(dǎo)致了Spring事務(wù)失效。
而如果加上了@Configuration注解,在調(diào)用dataSource()時(shí)會(huì)先去Spring容器中找DataSource,如果沒(méi)找到才回去調(diào)用方法創(chuàng)建一個(gè)。
到此這篇關(guān)于深入探究Spring底層核心原理的文章就介紹到這了,更多相關(guān)Spring底層原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java無(wú)鎖hashmap原理與實(shí)現(xiàn)詳解
本文主要介紹了java無(wú)鎖hashmap原理與實(shí)現(xiàn),大家參考使用吧2014-01-01
SpringCloud?Feign使用ApacheHttpClient代替默認(rèn)client方式
這篇文章主要介紹了SpringCloud?Feign使用ApacheHttpClient代替默認(rèn)client方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java使用訪問(wèn)者模式解決公司層級(jí)結(jié)構(gòu)圖問(wèn)題詳解
這篇文章主要介紹了Java使用訪問(wèn)者模式解決公司層級(jí)結(jié)構(gòu)圖問(wèn)題,結(jié)合實(shí)例形式分析了訪問(wèn)者模式的概念、原理及Java使用訪問(wèn)者模式解決公司曾經(jīng)結(jié)構(gòu)圖問(wèn)題的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-04-04
Java.lang.OutOfMemoryError: GC overhead limit
本文主要介紹了Java.lang.OutOfMemoryError: GC overhead limit exceeded錯(cuò)誤的解決,錯(cuò)誤是由于堆空間不足導(dǎo)致GC頻繁運(yùn)行,從而引起的,下面就來(lái)介紹一下解決方法2025-03-03
從HelloWorld和文檔注釋開(kāi)始入門(mén)Java編程
這篇文章主要介紹了從HelloWorld和文檔注釋開(kāi)始入門(mén)Java編程,涉及到Javadoc工具的使用,需要的朋友可以參考下2015-10-10
Java版超大整數(shù)階乘算法代碼詳解-10,0000級(jí)
這篇文章主要介紹了Java版超大整數(shù)階乘算法代碼詳解-10,0000級(jí),具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
Spring動(dòng)態(tài)管理定時(shí)任務(wù)之ThreadPoolTaskScheduler解讀
這篇文章主要介紹了Spring動(dòng)態(tài)管理定時(shí)任務(wù)之ThreadPoolTaskScheduler解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
深入理解java異常處理機(jī)制的原理和開(kāi)發(fā)應(yīng)用
Java異常處理機(jī)制在日常開(kāi)發(fā)中應(yīng)用頻繁,本篇文章主要在基礎(chǔ)的使用方法上,更進(jìn)一步的,如何更加合理的使用異常機(jī)制,希望可以對(duì)各位朋友能有所幫助。2017-04-04
SpringBoot中利用AOP和攔截器實(shí)現(xiàn)自定義注解
本文將通過(guò)攔截器+AOP實(shí)現(xiàn)自定義注解,在這里攔截器充當(dāng)在指定注解處要執(zhí)行的方法,aop負(fù)責(zé)將攔截器的方法和要注解生效的地方做一個(gè)織入,感興趣的可以嘗試一下2022-06-06

