javascript
Spring源码深度解析,Spring源码以及Bean的生命周期(五)(附代码示例:)
五)Bean 的生命周期,創建---初始化---銷毀的過程
目錄
五)Bean 的生命周期,創建---初始化---銷毀的過程
一 ,? 指定初始化方法 init-method 方法?? ?
二 ,指定銷毀 destory-method 方法
三,實現 InitializingBean 接口的 afterPropertiesSet()方法,當beanFactory 創建好對象,且把bean所有屬性設置好之后,相當于初始化方法。
實現 DisposableBean 的destory(),方法 當bean銷毀時,會把單例bean 進行銷毀
四,? ?可以使用JSR250規則定義的(java規范)兩個注解來實現,JDK自帶
五,Bean?的后置處理器,在?Bean?初始化之前調用進行攔截,在?bean?初始化前后進行一些處理工作,使用BeanPostProcessors 控制? Bean的生命周期。
實現? BeanPostProcessors兩個接口即可:
六 :項目Demo
一 ,? 指定初始化方法 init-method 方法
- 單實例 Bean,可以正常調用初始化和銷毀方法
- 多實例的?Bean,容器只負責初始化,但不會管理bean,容器關閉時不會調用銷毀方法
? ? 示例代碼:===》? ?項目 源碼? ====》? Cap8包:??xml 方式 指定
<!--創建Bike 類 bike 實例, 自定義初始化方法 init(),自定義銷毀方法 destory()--><bean id="bike" class="com.enjoy.Cap8.bean.Bike" init-method="init" destroy-method="destory"></bean>? ?注解實現===》項目 源碼? ====》? Cap8包:? ?(單實例模式下在容器創建之前實例化? Bean )? ? ?
//自定義初始化方法, 銷毀方法@Bean(initMethod = "init",destroyMethod = "destory")public Bike bike(){System.out.println("公交車到站了====》注冊到bean");return new Bike();}?
public class Bike {public Bike(){System.out.println("有一位乘客上車了=====>調類的構造方法");}//自定義bean 初始化方法public void init(){System.out.println("車啟動了====》 bean初始化方法");}//自定義bean 銷毀方法public void destory(){System.out.println("車爆炸了====》bean銷毀方法,關閉容器");} }? 測試結果:
@Testpublic static void main(String[] args){//創建上下文對象AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);app.close();}?
注解實現===》項目 源碼? ====》? Cap8包(多實例,容器在創建之前 不會去實例化 Bean ,只有當 getBean()? 的時候才會去 創建實例 )? ?
//自定義初始化方法, 銷毀方法,多實例模式下@Scope("prototype")@Bean(initMethod = "init",destroyMethod = "destory")public Bike bike(){System.out.println("公交車到站了====》注冊到bean");return new Bike();}? Bike? 與上面一致? ?測試 :
@Testpublic static void main(String[] args){//創建上下文對象AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);System.out.println("容器創建完成");//app.getBean("bike");app.close();}? ?當我沒有去getBean 的時候,? Bean 并沒有實例化
@Testpublic static void main(String[] args){//創建上下文對象AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);System.out.println("容器創建完成");app.getBean("bike");app.close();}? 結果顯而易見,? 在容器創建完成之后getBean()? 才會去 創建 Bean? 的實例 ,并且沒有調用銷毀方法
?
實現原理: 源碼跟蹤??
? ?
二 ,指定銷毀 destory-method 方法
? ? ? ? ? ? ? 示例代碼:見? ?5.1 代碼? ?====》項目源碼? Cap8;
三,實現 InitializingBean 接口的 afterPropertiesSet()方法,當beanFactory 創建好對象,且把bean所有屬性設置好之后,相當于初始化方法。
實現 DisposableBean 的destory(),方法 當bean銷毀時,會把單例bean 進行銷毀
示例源碼:?====》項目源碼? Cap8;
// 將 類注解為注解,讓容器掃描注入bean @Component public class Volkswagen implements InitializingBean, DisposableBean {public Volkswagen(){System.out.println("構造方法, 大眾cc,買到手");}//實現 DisposableBean 接口, destroy 銷毀方法@Overridepublic void destroy() throws Exception {System.out.println("大眾cc,沒了。。===》 容器銷毀");}//實現 InitializingBean 接口, afterPropertiesSet() 初始化方法@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("大眾cc,最愛。。===》 bean初始化");} }在配置類 增加掃描注解 將 該包下面的掃描到容器中?
@Configuration //掃描包下所有組件,并注入bean 到容器 @ComponentScan("com.enjoy.Cap8.bean") public class Cap8MainConfigOfLifeCycle {//自定義初始化方法, 銷毀方法,多實例模式下@Scope("prototype")@Bean(initMethod = "init",destroyMethod = "destory")public Bike bike(){System.out.println("公交車到站了====》注冊到bean");return new Bike();}}測試:
@Testpublic static void main(String[] args){//創建上下文對象AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);System.out.println("容器創建完成");//System.out.println(app.getBean("bike"));System.out.println(app.getBean("volkswagen"));app.close();}四,? ?可以使用JSR250規則定義的(java規范)兩個注解來實現,JDK自帶
- ? ? ? ? ? @PostConstruct : 在Bean 創建完成,且shu屬于賦值完成后進行初始化,屬于JDK規范的注解
- ? ? ? ? ? @PreDestroy? ?:? ? 在Bean? 將被移除之前進行通知,在容器銷毀之前進行清理工作
示例源碼:?====》項目源碼? Cap8;
@Component public class Benz {public Benz(){System.out.println("構造方法,買了一輛奔馳");}//使用JSR250規則定義 JDK 自帶注解 初始化 bean@PostConstructpublic void init(){System.out.println("奔馳漏油了 ====》初始bean");}//使用JSR250規則定義 JDK 自帶注解 容器銷毀@PreDestroypublic void destroy(){System.out.println("奔馳爆炸了 ====》容器銷毀");} }在配置類 增加掃描注解 將 該包下面的掃描到容器中?
@Configuration //掃描包下所有組件,并注入bean 到容器 @ComponentScan("com.enjoy.Cap8.bean") public class Cap8MainConfigOfLifeCycle {//自定義初始化方法, 銷毀方法,多實例模式下@Scope("prototype")@Bean(initMethod = "init",destroyMethod = "destory")public Bike bike(){System.out.println("公交車到站了====》注冊到bean");return new Bike();}}測試?
@Testpublic static void main(String[] args){//創建上下文對象AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);System.out.println("容器創建完成");//System.out.println(app.getBean("bike"));//System.out.println(app.getBean("volkswagen"));System.out.println(app.getBean("benz"));app.close();}五,Bean?的后置處理器,在?Bean?初始化之前調用進行攔截,在?bean?初始化前后進行一些處理工作,使用BeanPostProcessors 控制? Bean的生命周期。
實現? BeanPostProcessors兩個接口即可:
- ?postProcessBeforelnitialization()? ? 在Bean? 初始化之前? ? ? ?進行攔截 增強
- ?postProcessAfterInitalization()? ? ? ? 在Bean? 初始化之后? ? ?? 進行攔截 增強
Spring 底層對?BeanPostProcessor?的使用,包括 bean 的賦值,注入其他組件,生命周期注解功能等。 如:
- ApplicationContextAwareProcesspor? 接口? ? 這個后置處理器其實就是判斷我們的 bean 有沒有實現? ApplicationContextAware 這個接口? ,并處理相應的邏輯,
- BeanValidationPostProcess 接口? 數據校驗
- InitDestroyAnnotationBeanPostProcessor 接口? 此處理器? 是用來處理? ?上述 5.4@PostConstruct? @PreDestroy? ?讓 容器 找到 init 方法 和? destroy 方法?
?
? ? 示例源碼:?====》項目源碼? Cap8;
?實現? BeanPostProcessors 接口, 里面的兩個方法
@Component public class Bmw implements BeanPostProcessor {/**Aop 在初始化bean 攔截 進行增強 做一些操作,如 任何bean 初始化回調或自定義初始化方法之前,*將此BeanPostProcessor應用于給定的新bean實例 bean已經填充了屬性值。 返回的bean實例可能是原始實例的包裝器**/@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization=====>"+bean+"===>"+beanName);return bean;}/**Aop 在初始化bean 攔截 進行增強 做一些操作,如 一般的Aop 事務 在事件之后 commit,*在bean初始完后 攔截 增強 對于FactoryBean,將為FactoryBean 實例和FactoryBean創建的對象調用此回調。 * 處理器可以通過相應的檢查來決定是應用于FactoryBean還是應用于創建的對象。 與所有其他BeanPostProcessor回調相比**/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization=====>"+bean+"===>"+beanName);return bean;} }?
配置類 ; 為了便于觀察? ?當前 只是 掃描到? benz 這個類??
@Configuration //掃描包下所有組件,并注入bean 到容器 @ComponentScan("com.enjoy.Cap8.bean") public class Cap8MainConfigOfLifeCycle {//自定義初始化方法, 銷毀方法,多實例模式下//@Scope("prototype")//@Bean(initMethod = "init",destroyMethod = "destory")public Bike bike(){System.out.println("公交車到站了====》注冊到bean");return new Bike();}}測試:
@Testpublic static void main(String[] args){//創建上下文對象AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);System.out.println("容器創建完成");//System.out.println(app.getBean("bike"));//System.out.println(app.getBean("volkswagen"));System.out.println(app.getBean("benz"));app.close();}觀察結果
? ??
六 :項目Demo
Spring源碼深度解析,(附代碼示例 碼云地址: https://gitee.com/Crazycw/SpringCode.git)
參考資料:??https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/
請看下篇: Spring源碼深度解析,初始Spring源碼(六)(附代碼示例:)
?
總結
以上是生活随笔為你收集整理的Spring源码深度解析,Spring源码以及Bean的生命周期(五)(附代码示例:)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言c20,C20、C30、C50混凝
- 下一篇: nodeJS项目建立流程