摘要:如果該方法的返回值代替原本該生成的目標(biāo)對(duì)象,后續(xù)只有方法會(huì)調(diào)用,其它方法不再調(diào)用否則按照正常的流程走方法在目標(biāo)對(duì)象實(shí)例化之后調(diào)用,這個(gè)時(shí)候?qū)ο笠呀?jīng)被實(shí)例化,但是該實(shí)例的屬性還未被設(shè)置,都是。
我們可能會(huì)在 Bean 對(duì)象創(chuàng)建完成后, 執(zhí)行某些操作或在銷毀前做某些操作.
我們可以實(shí)現(xiàn) InitializingBean 或 DisposableBean 接口
public class Test implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { } @Override public void destroy() throws Exception { } }
當(dāng)然我們可以使用注解來實(shí)現(xiàn)
@PostConstruct public void afterPropertiesSet() throws Exception { System.out.println("-- init --"); } @PreDestroy public void destroy() throws Exception { System.out.println("-- destroy --"); }
還有另一種方法可以使用 @Bean 注解
public void afterPropertiesSet() throws Exception { System.out.println("-- init --"); } public void destroy() throws Exception { System.out.println("-- destroy --"); } @Bean(initMethod = "afterPropertiesSet", destroyMethod = "destroy") public Test getTest() { return new Test(); }
要注意的是, 初始化和銷毀的方法只是針對(duì)當(dāng)前的 bean 不會(huì)對(duì)其它 bean 產(chǎn)生影響.
如果想所有的 bean 在創(chuàng)建前或創(chuàng)建后添加一些處理邏輯, 可以使用 BeanPostProcessor 接口. 也可以配合 Ordered 接口來設(shè)置執(zhí)行順序.
如果有兩個(gè)容器, 他們之間不會(huì)相互影響.
BeanPostProcessor 接口由兩個(gè)回調(diào)方法組成.
public interface BeanPostProcessor { // 初始化之前的操作 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; // 初始化之后的操作 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
四個(gè)子接口:
1.DestructionAwareBeanPostProcessor
// 該方法是bean在Spring在容器中被銷毀之前調(diào)用 void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
2.InstantiationAwareBeanPostProcessor
// postProcessBeforeInstantiation方法的作用在目標(biāo)對(duì)象被實(shí)例化之前調(diào)用的方法,可以返回目標(biāo)實(shí)例的一個(gè)代理用來代替目標(biāo)實(shí)例 // beanClass參數(shù)表示目標(biāo)對(duì)象的類型,beanName是目標(biāo)實(shí)例在Spring容器中的name // 返回值類型是Object,如果返回的是非null對(duì)象,接下來除了postProcessAfterInitialization方法會(huì)被執(zhí)行以外,其它bean構(gòu)造的那些方法都不再執(zhí)行。否則那些過程以及postProcessAfterInitialization方法都會(huì)執(zhí)行 Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException; // postProcessAfterInstantiation方法的作用在目標(biāo)對(duì)象被實(shí)例化之后并且在屬性值被populate之前調(diào)用 // bean參數(shù)是目標(biāo)實(shí)例(這個(gè)時(shí)候目標(biāo)對(duì)象已經(jīng)被實(shí)例化但是該實(shí)例的屬性還沒有被設(shè)置),beanName是目標(biāo)實(shí)例在Spring容器中的name // 返回值是boolean類型,如果返回true,目標(biāo)實(shí)例內(nèi)部的返回值會(huì)被populate,否則populate這個(gè)過程會(huì)被忽視 boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException; // postProcessPropertyValues方法的作用在屬性中被設(shè)置到目標(biāo)實(shí)例之前調(diào)用,可以修改屬性的設(shè)置 // pvs參數(shù)表示參數(shù)屬性值(從BeanDefinition中獲取),pds代表參數(shù)的描述信息(比如參數(shù)名,類型等描述信息),bean參數(shù)是目標(biāo)實(shí)例,beanName是目標(biāo)實(shí)例在Spring容器中的name // 返回值是PropertyValues,可以使用一個(gè)全新的PropertyValues代替原先的PropertyValues用來覆蓋屬性設(shè)置或者直接在參數(shù)pvs上修改。如果返回值是null,那么會(huì)忽略屬性設(shè)置這個(gè)過程(所有屬性不論使用什么注解,最后都是null) PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
注: 此接口為專用接口, 主要用于框架內(nèi)部使用. 建議盡可能地實(shí)現(xiàn)普通 BeanPostProcessor 接口, 或 InstantiationAwareBeanPostProcessorAdapter 派生, 以避免擴(kuò)展到該接口.
InstantiationAwareBeanPostProcessor接口繼承BeanPostProcessor接口,它內(nèi)部提供了3個(gè)方法,再加上BeanPostProcessor接口內(nèi)部的2個(gè)方法,所以實(shí)現(xiàn)這個(gè)接口需要實(shí)現(xiàn)5個(gè)方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目標(biāo)對(duì)象的實(shí)例化過程中需要處理的事情,包括實(shí)例化對(duì)象的前后過程以及實(shí)例的屬性設(shè)置
postProcessBeforeInstantiation方法是最先執(zhí)行的方法,它在目標(biāo)對(duì)象實(shí)例化之前調(diào)用,該方法的返回值類型是Object,我們可以返回任何類型的值。由于這個(gè)時(shí)候目標(biāo)對(duì)象還未實(shí)例化,所以這個(gè)返回值可以用來代替原本該生成的目標(biāo)對(duì)象的實(shí)例(比如代理對(duì)象)。如果該方法的返回值代替原本該生成的目標(biāo)對(duì)象,后續(xù)只有postProcessAfterInitialization方法會(huì)調(diào)用,其它方法不再調(diào)用;否則按照正常的流程走
postProcessAfterInstantiation方法在目標(biāo)對(duì)象實(shí)例化之后調(diào)用,這個(gè)時(shí)候?qū)ο笠呀?jīng)被實(shí)例化,但是該實(shí)例的屬性還未被設(shè)置,都是null。如果該方法返回false,會(huì)忽略屬性值的設(shè)置;如果返回true,會(huì)按照正常流程設(shè)置屬性值
postProcessPropertyValues方法對(duì)屬性值進(jìn)行修改(這個(gè)時(shí)候?qū)傩灾颠€未被設(shè)置,但是我們可以修改原本該設(shè)置進(jìn)去的屬性值)。如果postProcessAfterInstantiation方法返回false,該方法不會(huì)被調(diào)用??梢栽谠摲椒▋?nèi)對(duì)屬性值進(jìn)行修改
父接口BeanPostProcessor的2個(gè)方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目標(biāo)對(duì)象被實(shí)例化之后,并且屬性也被設(shè)置之后調(diào)用的
Instantiation表示實(shí)例化,Initialization表示初始化。實(shí)例化的意思在對(duì)象還未生成,初始化的意思在對(duì)象已經(jīng)生成
3.SmartInstantiationAwareBeanPostProcessor
// 預(yù)測(cè)Bean的類型,返回第一個(gè)預(yù)測(cè)成功的Class類型,如果不能預(yù)測(cè)返回null Class> predictBeanType(Class> beanClass, String beanName) throws BeansException; // 選擇合適的構(gòu)造器,比如目標(biāo)對(duì)象有多個(gè)構(gòu)造器,在這里可以進(jìn)行一些定制化,選擇合適的構(gòu)造器 // beanClass參數(shù)表示目標(biāo)實(shí)例的類型,beanName是目標(biāo)實(shí)例在Spring容器中的name // 返回值是個(gè)構(gòu)造器數(shù)組,如果返回null,會(huì)執(zhí)行下一個(gè)PostProcessor的determineCandidateConstructors方法;否則選取該P(yáng)ostProcessor選擇的構(gòu)造器 Constructor>[] determineCandidateConstructors(Class> beanClass, String beanName) throws BeansException; // 獲得提前暴露的bean引用。主要用于解決循環(huán)引用的問題 // 只有單例對(duì)象才會(huì)調(diào)用此方法 Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
SmartInstantiationAwareBeanPostProcessor接口繼承InstantiationAwareBeanPostProcessor接口,它內(nèi)部提供了3個(gè)方法,再加上父接口的5個(gè)方法,所以實(shí)現(xiàn)這個(gè)接口需要實(shí)現(xiàn)8個(gè)方法。SmartInstantiationAwareBeanPostProcessor接口的主要作用也是在于目標(biāo)對(duì)象的實(shí)例化過程中需要處理的事情。它是InstantiationAwareBeanPostProcessor接口的一個(gè)擴(kuò)展。主要在Spring框架內(nèi)部使用
predictBeanType方法用于預(yù)測(cè)Bean的類型,返回第一個(gè)預(yù)測(cè)成功的Class類型,如果不能預(yù)測(cè)返回null。主要在于BeanDefinition無(wú)法確定Bean類型的時(shí)候調(diào)用該方法來確定類型
determineCandidateConstructors方法用于選擇合適的構(gòu)造器,比如類有多個(gè)構(gòu)造器,可以實(shí)現(xiàn)這個(gè)方法選擇合適的構(gòu)造器并用于實(shí)例化對(duì)象。該方法在postProcessBeforeInstantiation方法和postProcessAfterInstantiation方法之間調(diào)用,如果postProcessBeforeInstantiation方法返回了一個(gè)新的實(shí)例代替了原本該生成的實(shí)例,那么該方法會(huì)被忽略
getEarlyBeanReference主要用于解決循環(huán)引用問題。比如ReferenceA實(shí)例內(nèi)部有ReferenceB的引用,ReferenceB實(shí)例內(nèi)部有ReferenceA的引用。首先先實(shí)例化ReferenceA,實(shí)例化完成之后提前把這個(gè)bean暴露在ObjectFactory中,然后populate屬性,這個(gè)時(shí)候發(fā)現(xiàn)需要ReferenceB。然后去實(shí)例化ReferenceB,在實(shí)例化ReferenceB的時(shí)候它需要ReferenceA的實(shí)例才能繼續(xù),這個(gè)時(shí)候就會(huì)去ObjectFactory中找出了ReferenceA實(shí)例,ReferenceB順利實(shí)例化。ReferenceB實(shí)例化之后,ReferenceA的populate屬性過程也成功完成,注入了ReferenceB實(shí)例。提前把這個(gè)bean暴露在ObjectFactory中,這個(gè)ObjectFactory獲取的實(shí)例就是通過getEarlyBeanReference方法得到的
4.MergedBeanDefinitionPostProcessor
// 該方法是bean在合并Bean定義之后調(diào)用 void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/72465.html
摘要:上一篇文章生命周期之我從哪里來說明了我是誰(shuí)和我從哪里來的兩大哲學(xué)問題,今天我們要討論一下終極哲學(xué)我要到哪里去初始化有三種方式銷毀同樣有三種方式正所謂,天對(duì)地,雨對(duì)風(fēng)對(duì)對(duì)對(duì)雷隱隱,霧蒙蒙山花對(duì)海樹,赤日對(duì)蒼穹平仄平仄平平仄,仄平仄平仄 上一篇文章 Spring Bean 生命周期之我從哪里來 說明了我是誰(shuí)? 和 我從哪里來? 的兩大哲學(xué)問題,今天我們要討論一下終極哲學(xué)我要到哪里去?sho...
摘要:初始化我們知道容器初始化后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的定義進(jìn)行的初始化操作,所以我們分析源碼的入口也就是在容器初始化的入口,分析容器初始化后在什么地方開始第一次的初始化。 前言 Spring IOC容器在初始化之后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的bean定義進(jìn)行bean的初始化操作,同時(shí)會(huì)也涉及到Bean的后置處理器以及DI(依賴注入)等行為。對(duì)于Bean的初始化,...
摘要:的在單例被破壞時(shí)由進(jìn)行方法調(diào)用。定義并實(shí)現(xiàn)這兩個(gè)接口容器創(chuàng)建完成注解是的縮寫,意思是規(guī)范提案。在創(chuàng)建完成并且屬性賦值完成來執(zhí)行初始化方法在容器銷毀之前回調(diào)通知支持自動(dòng)裝配,類似。 Spring注解應(yīng)用篇--IOC容器Bean生命周期 這是Spring注解專題系類文章,本系類文章適合Spring入門者或者原理入門者,小編會(huì)在本系類文章下進(jìn)行企業(yè)級(jí)應(yīng)用實(shí)戰(zhàn)講解以及spring源碼跟進(jìn)。本文...
摘要:生成的兩種方式通過反射調(diào)用構(gòu)造函數(shù)通過優(yōu)點(diǎn)依賴關(guān)系的管理被反轉(zhuǎn)并交給容器,使復(fù)雜的依賴關(guān)系管理從應(yīng)用中解放出來。 IOC概述 1、理解: (1)控制反轉(zhuǎn)。將生成對(duì)象的控制權(quán)交IOC容器,由容器生成依賴的對(duì)象。調(diào)用類只依賴接口,而不依賴具體的實(shí)現(xiàn)類,減少了耦合。在運(yùn)行的時(shí)候,才由容器將具體的實(shí)例注入到調(diào)用類的對(duì)象中。(2)依賴注入,就是向Ioc容器索要bean的過程。getBean是依賴...
摘要:如果依賴靠構(gòu)造器方式注入,則無(wú)法處理,直接會(huì)報(bào)循環(huán)依賴異常。光繼承這個(gè)接口還不夠,繼承這個(gè)接口只能獲取,要想讓生效,還需要拿到切面對(duì)象包含和才行。有了目標(biāo)對(duì)象,所有的切面類,此時(shí)就可以為生成代理對(duì)象了。 Spring 是一個(gè)輕量級(jí)的 J2EE 開源框架,其目標(biāo)是降低企業(yè)級(jí)應(yīng)用開發(fā)難度,提高企業(yè)級(jí)應(yīng)用開發(fā)效率。在日程開發(fā)中,我們會(huì)經(jīng)常使用 Spring 框架去構(gòu)建應(yīng)用。所以作為一個(gè)經(jīng)常使...
閱讀 800·2021-11-18 10:02
閱讀 2371·2021-11-15 18:13
閱讀 3396·2021-11-15 11:38
閱讀 3163·2021-09-22 15:55
閱讀 3809·2021-08-09 13:43
閱讀 2609·2021-07-25 14:19
閱讀 2541·2019-08-30 14:15
閱讀 3526·2019-08-30 14:15