深入探究Spring底層核心原理
Spring底層核心原理
下面這幾行代碼是一個(gè)Spring的入門代碼,第一行是通過java配置類 注解的方式創(chuàng)建一個(gè)Spring容器,第二行是通過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ì)象 存入容器中
- 使用
- 銷毀
執(zhí)行DisposableBean
接口的destroy()
方法
有@PreDestroy
注解的方法
XML 配置文件中destroy-method
屬性指定的方法
推斷構(gòu)造方法
如果沒有寫構(gòu)造方法,那么Spring會(huì)執(zhí)行默認(rèn)空參的構(gòu)造方法
如果顯示寫了一個(gè)構(gòu)造方法,那么Spring就會(huì)使用這個(gè)構(gòu)造方法,構(gòu)造方法中如果有參數(shù)那么會(huì)進(jìn)行依賴注入
如果顯示寫了多個(gè)構(gòu)造方法并有空參的構(gòu)造方法時(shí),會(huì)執(zhí)行空參的構(gòu)造方法
如果顯示寫了多個(gè)構(gòu)造方法沒有空參的構(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屬性來存儲(chǔ)普通對(duì)象,代理對(duì)象中重寫要執(zhí)行的方法,首先執(zhí)行增強(qiáng)邏輯,然后通過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)邏輯來執(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
注解 - 如果存在則通過事務(wù)管理器創(chuàng)建一個(gè)connection連接對(duì)象
- autoCommit設(shè)置為false
- 去執(zhí)行目標(biāo)方法target.method()
- 如果出現(xiàn)了異常則回滾rollback(),沒有異常則提交commit()
如果上面的配置類中不加@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,如果沒找到才回去調(diào)用方法創(chuàng)建一個(gè)。
到此這篇關(guān)于深入探究Spring底層核心原理的文章就介紹到這了,更多相關(guān)Spring底層原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中如何解決讀取properties文件讀取問題
這篇文章主要介紹了SpringBoot中如何解決讀取properties文件讀取問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Java數(shù)據(jù)結(jié)構(gòu)之樹和二叉樹的相關(guān)資料
這篇文章主要介紹了Java?數(shù)據(jù)結(jié)構(gòu)之樹和二叉樹相關(guān)資料,文中通過示例代碼和一些相關(guān)題目來做介紹,非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下!2023-01-01Java數(shù)據(jù)結(jié)構(gòu)之LinkedList的用法詳解
鏈表(Linked?list)是一種常見的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),是一種線性表。Java的LinkedList(鏈表)?類似于?ArrayList,是一種常用的數(shù)據(jù)容器,本文就來簡(jiǎn)單講講它的使用吧2023-05-05java中類和對(duì)象的知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了一篇關(guān)于java中類和對(duì)象的知識(shí)點(diǎn)總結(jié),有需要的朋友們可以學(xué)習(xí)下。2020-12-12Java中final關(guān)鍵字的使用與注意總結(jié)
這篇文章主要給大家介紹了關(guān)于Java中final關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08