资讯专栏INFORMATION COLUMN

Bean 的生命周期回调

xorpay / 1150人阅读

摘要:如果该方法的返回值代替原本该生成的目标对象,后续只有方法会调用,其它方法不再调用否则按照正常的流程走方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是。

我们可能会在 Bean 对象创建完成后, 执行某些操作或在销毁前做某些操作.

我们可以实现 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 注解

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 产生影响.

如果想所有的 bean 在创建前或创建后添加一些处理逻辑, 可以使用 BeanPostProcessor 接口. 也可以配合 Ordered 接口来设置执行顺序.

如果有两个容器, 他们之间不会相互影响.

BeanPostProcessor 接口由两个回调方法组成.

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 派生, 以避免扩展到该接口.

InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置

postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。如果该方法返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值

postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法不会被调用。可以在该方法内对属性值进行修改

父接口BeanPostProcessor的2个方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目标对象被实例化之后,并且属性也被设置之后调用的

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;

SmartInstantiationAwareBeanPostProcessor接口继承InstantiationAwareBeanPostProcessor接口,它内部提供了3个方法,再加上父接口的5个方法,所以实现这个接口需要实现8个方法。SmartInstantiationAwareBeanPostProcessor接口的主要作用也是在于目标对象的实例化过程中需要处理的事情。它是InstantiationAwareBeanPostProcessor接口的一个扩展。主要在Spring框架内部使用

predictBeanType方法用于预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null。主要在于BeanDefinition无法确定Bean类型的时候调用该方法来确定类型

determineCandidateConstructors方法用于选择合适的构造器,比如类有多个构造器,可以实现这个方法选择合适的构造器并用于实例化对象。该方法在postProcessBeforeInstantiation方法和postProcessAfterInstantiation方法之间调用,如果postProcessBeforeInstantiation方法返回了一个新的实例代替了原本该生成的实例,那么该方法会被忽略

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72465.html

相关文章

  • Spring Bean 生命周期之destroy——终极信仰

    摘要:上一篇文章生命周期之我从哪里来说明了我是谁和我从哪里来的两大哲学问题,今天我们要讨论一下终极哲学我要到哪里去初始化有三种方式销毁同样有三种方式正所谓,天对地,雨对风对对对雷隐隐,雾蒙蒙山花对海树,赤日对苍穹平仄平仄平平仄,仄平仄平仄 上一篇文章 Spring Bean 生命周期之我从哪里来 说明了我是谁? 和 我从哪里来? 的两大哲学问题,今天我们要讨论一下终极哲学我要到哪里去?sho...

    JouyPub 评论0 收藏0
  • Spring专题之Bean初始化源码分析(1)

    摘要:初始化我们知道容器初始化后会对容器中非懒加载的,单例的以及非抽象的定义进行的初始化操作,所以我们分析源码的入口也就是在容器初始化的入口,分析容器初始化后在什么地方开始第一次的初始化。 前言 Spring IOC容器在初始化之后会对容器中非懒加载的,单例的以及非抽象的bean定义进行bean的初始化操作,同时会也涉及到Bean的后置处理器以及DI(依赖注入)等行为。对于Bean的初始化,...

    harryhappy 评论0 收藏0
  • Spring注解专题系类(二)

    摘要:的在单例被破坏时由进行方法调用。定义并实现这两个接口容器创建完成注解是的缩写,意思是规范提案。在创建完成并且属性赋值完成来执行初始化方法在容器销毁之前回调通知支持自动装配,类似。 Spring注解应用篇--IOC容器Bean生命周期 这是Spring注解专题系类文章,本系类文章适合Spring入门者或者原理入门者,小编会在本系类文章下进行企业级应用实战讲解以及spring源码跟进。本文...

    Alex 评论0 收藏0
  • Spring知识——IOC容器

    摘要:生成的两种方式通过反射调用构造函数通过优点依赖关系的管理被反转并交给容器,使复杂的依赖关系管理从应用中解放出来。 IOC概述 1、理解: (1)控制反转。将生成对象的控制权交IOC容器,由容器生成依赖的对象。调用类只依赖接口,而不依赖具体的实现类,减少了耦合。在运行的时候,才由容器将具体的实例注入到调用类的对象中。(2)依赖注入,就是向Ioc容器索要bean的过程。getBean是依赖...

    yexiaobai 评论0 收藏0
  • Spring bean生命流程

    摘要:如果依赖靠构造器方式注入,则无法处理,直接会报循环依赖异常。光继承这个接口还不够,继承这个接口只能获取,要想让生效,还需要拿到切面对象包含和才行。有了目标对象,所有的切面类,此时就可以为生成代理对象了。 Spring 是一个轻量级的 J2EE 开源框架,其目标是降低企业级应用开发难度,提高企业级应用开发效率。在日程开发中,我们会经常使用 Spring 框架去构建应用。所以作为一个经常使...

    赵连江 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<