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);
相关文章
相关标签/搜索