Bean 的生命週期回調

咱們可能會在 Bean 對象建立完成後, 執行某些操做或在銷燬前作某些操做.java

咱們能夠實現 InitializingBeanDisposableBean 接口數組

public class Test implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception {

    }
    
    @Override
    public void destroy() throws Exception {
        
    }

}

固然咱們可使用註解來實現框架

@PostConstruct
public void afterPropertiesSet() throws Exception {
    System.out.println("-- init --");
}

@PreDestroy
public void destroy() throws Exception {
    System.out.println("-- destroy --");
}

還有另外一種方法可使用 @Bean 註解ide

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();
}

要注意的是, 初始化和銷燬的方法只是針對當前的 bean 不會對其它 bean 產生影響. post

若是想全部的 bean 在建立前或建立後添加一些處理邏輯, 可使用 BeanPostProcessor 接口. 也能夠配合 Ordered 接口來設置執行順序.代理

若是有兩個容器, 他們之間不會相互影響.

BeanPostProcessor 接口由兩個回調方法組成.code

public interface BeanPostProcessor {
    // 初始化以前的操做
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // 初始化以後的操做
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

四個子接口:對象

1.DestructionAwareBeanPostProcessor繼承

// 該方法是bean在Spring在容器中被銷燬以前調用
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

2.InstantiationAwareBeanPostProcessor接口

// postProcessBeforeInstantiation方法的做用在目標對象被實例化以前調用的方法,能夠返回目標實例的一個代理用來代替目標實例
// beanClass參數表示目標對象的類型,beanName是目標實例在Spring容器中的name
// 返回值類型是Object,若是返回的是非null對象,接下來除了postProcessAfterInitialization方法會被執行之外,其它bean構造的那些方法都再也不執行。不然那些過程以及postProcessAfterInitialization方法都會執行
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

// postProcessAfterInstantiation方法的做用在目標對象被實例化以後而且在屬性值被populate以前調用
// bean參數是目標實例(這個時候目標對象已經被實例化可是該實例的屬性尚未被設置),beanName是目標實例在Spring容器中的name
// 返回值是boolean類型,若是返回true,目標實例內部的返回值會被populate,不然populate這個過程會被忽視
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

// postProcessPropertyValues方法的做用在屬性中被設置到目標實例以前調用,能夠修改屬性的設置
// pvs參數表示參數屬性值(從BeanDefinition中獲取),pds表明參數的描述信息(好比參數名,類型等描述信息),bean參數是目標實例,beanName是目標實例在Spring容器中的name
// 返回值是PropertyValues,可使用一個全新的PropertyValues代替原先的PropertyValues用來覆蓋屬性設置或者直接在參數pvs上修改。若是返回值是null,那麼會忽略屬性設置這個過程(全部屬性不論使用什麼註解,最後都是null)
PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
    throws BeansException;
注: 此接口爲專用接口, 主要用於框架內部使用. 建議儘量地實現普通 BeanPostProcessor 接口, 或 InstantiationAwareBeanPostProcessorAdapter 派生, 以免擴展到該接口.
  1. InstantiationAwareBeanPostProcessor接口繼承BeanPostProcessor接口,它內部提供了3個方法,再加上BeanPostProcessor接口內部的2個方法,因此實現這個接口須要實現5個方法。InstantiationAwareBeanPostProcessor接口的主要做用在於目標對象的實例化過程當中須要處理的事情,包括實例化對象的先後過程以及實例的屬性設置
  2. postProcessBeforeInstantiation方法是最早執行的方法,它在目標對象實例化以前調用,該方法的返回值類型是Object,咱們能夠返回任何類型的值。因爲這個時候目標對象還未實例化,因此這個返回值能夠用來代替本來該生成的目標對象的實例(好比代理對象)。若是該方法的返回值代替本來該生成的目標對象,後續只有postProcessAfterInitialization方法會調用,其它方法再也不調用;不然按照正常的流程走
  3. postProcessAfterInstantiation方法在目標對象實例化以後調用,這個時候對象已經被實例化,可是該實例的屬性還未被設置,都是null。若是該方法返回false,會忽略屬性值的設置;若是返回true,會按照正常流程設置屬性值
  4. postProcessPropertyValues方法對屬性值進行修改(這個時候屬性值還未被設置,可是咱們能夠修改本來該設置進去的屬性值)。若是postProcessAfterInstantiation方法返回false,該方法不會被調用。能夠在該方法內對屬性值進行修改
  5. 父接口BeanPostProcessor的2個方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目標對象被實例化以後,而且屬性也被設置以後調用的
  6. Instantiation表示實例化,Initialization表示初始化。實例化的意思在對象還未生成,初始化的意思在對象已經生成

3.SmartInstantiationAwareBeanPostProcessor

// 預測Bean的類型,返回第一個預測成功的Class類型,若是不能預測返回null
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

// 選擇合適的構造器,好比目標對象有多個構造器,在這裏能夠進行一些定製化,選擇合適的構造器
// beanClass參數表示目標實例的類型,beanName是目標實例在Spring容器中的name
// 返回值是個構造器數組,若是返回null,會執行下一個PostProcessor的determineCandidateConstructors方法;不然選取該PostProcessor選擇的構造器
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

// 得到提早暴露的bean引用。主要用於解決循環引用的問題
// 只有單例對象纔會調用此方法
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
  1. SmartInstantiationAwareBeanPostProcessor接口繼承InstantiationAwareBeanPostProcessor接口,它內部提供了3個方法,再加上父接口的5個方法,因此實現這個接口須要實現8個方法。SmartInstantiationAwareBeanPostProcessor接口的主要做用也是在於目標對象的實例化過程當中須要處理的事情。它是InstantiationAwareBeanPostProcessor接口的一個擴展。主要在Spring框架內部使用
  2. predictBeanType方法用於預測Bean的類型,返回第一個預測成功的Class類型,若是不能預測返回null。主要在於BeanDefinition沒法肯定Bean類型的時候調用該方法來肯定類型
  3. determineCandidateConstructors方法用於選擇合適的構造器,好比類有多個構造器,能夠實現這個方法選擇合適的構造器並用於實例化對象。該方法在postProcessBeforeInstantiation方法和postProcessAfterInstantiation方法之間調用,若是postProcessBeforeInstantiation方法返回了一個新的實例代替了本來該生成的實例,那麼該方法會被忽略
  4. getEarlyBeanReference主要用於解決循環引用問題。好比ReferenceA實例內部有ReferenceB的引用,ReferenceB實例內部有ReferenceA的引用。首先先實例化ReferenceA,實例化完成以後提早把這個bean暴露在ObjectFactory中,而後populate屬性,這個時候發現須要ReferenceB。而後去實例化ReferenceB,在實例化ReferenceB的時候它須要ReferenceA的實例才能繼續,這個時候就會去ObjectFactory中找出了ReferenceA實例,ReferenceB順利實例化。ReferenceB實例化以後,ReferenceA的populate屬性過程也成功完成,注入了ReferenceB實例。提早把這個bean暴露在ObjectFactory中,這個ObjectFactory獲取的實例就是經過getEarlyBeanReference方法獲得的

4.MergedBeanDefinitionPostProcessor

// 該方法是bean在合併Bean定義以後調用
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
相關文章
相關標籤/搜索