千家信息网

使用spring容器在初始化Bean时前和后的操作是怎样的

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇文章给大家分享的是有关使用spring容器在初始化Bean时前和后的操作是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧spri
千家信息网最后更新 2026年11月01日使用spring容器在初始化Bean时前和后的操作是怎样的

本篇文章给大家分享的是有关使用spring容器在初始化Bean时前和后的操作是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧

spring容器初始化Bean操作

在某些情况下,Spring容器在初始化Bean的时候,希望在初始化bean前和销毁bean前进行一些资源的加载和释放的操作。可以通过一下三种方式完成。

  • Bean的方法加上@PostConstruct和@PreDestroy注解

  • 在xml中定义init-method和destory-method方法

  • Bean实现InitializingBean和DisposableBean接口

@PostConstruct和@PreDestroy注解

JavaBean代码

@Componentpublic class PersonService {    private String message;    public String getMessage() {        return message;    }    public void setMessage(String message) {        this.message = message;    }    @PostConstruct    public void init() {        System.out.println("PersonService.class init method ...");    }    @PreDestroy    public void cleanUp() {        System.out.println("PersonService.class cleanUp method ...");    }}

spring配置文件

        

测试代码和结果

测试代码

public static void main(String[] args) {     AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring-zhujie.xml");     context.registerShutdownHook();}

运行结果

PersonService.class init method ...

PersonService.class cleanUp method ...

在XML中定义init-method和destory-method方法

JavaBean代码

public class PersonService {    private String message;    public String getMessage() {        return message;    }    public void setMessage(String message) {        this.message = message;    }    public void init() {        System.out.println("PersonService.class init method ...");    }    public void cleanUp() {        System.out.println("PersonService.class cleanUp method ...");    }}

spring配置文件

测试代码和结果

测试代码

public static void main(String[] args) {        AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring-xml.xml");        context.registerShutdownHook();}

运行结果

PersonService.class init method ...

六月 23, 2017 9:42:06 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose

信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@7a94c5e7: startup date [Fri Jun 23 21:42:06 CST 2017]; root of context hierarchy

PersonService.class cleanUp method ...

Bean实现InitializingBean和DisposableBean接口

JavaBean代码

public class PersonService implements InitializingBean, DisposableBean {    private String message;    public String getMessage() {        return message;    }    public void setMessage(String message) {        this.message = message;    }    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("PersonService.class init method ...");    }    @Override    public void destroy() throws Exception {        System.out.println("PersonService.class cleanUp method ...");    }}

spring配置文件

测试代码和结果

测试代码

public static void main(String[] args) {        AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring-interface.xml");        context.registerShutdownHook();    }

运行结果

PersonService.class init method ...

PersonService.class cleanUp method ...

Spring bean 初始化顺序

InitializingBean, init-method 和 PostConstruct

1、概述

从接口的名字上不难发现,InitializingBean 的作用就是在 bean 初始化后执行定制化的操作。

Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种:

通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法;

通过 元素的 init-method/destroy-method 属性指定初始化之后 /销毁之前调用的操作方法;

在指定方法上加上@PostConstruct 或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用。

2、InitializingBean vs init-method

接口定义如下:

public interface InitializingBean {    void afterPropertiesSet() throws Exception;}

接口只有一个方法afterPropertiesSet,

此方法的调用入口是负责加载 spring bean 的AbstractAutowireCapableBeanFactory,源码如下:

protected void invokeInitMethods(String beanName, Object bean,   RootBeanDefinition mbd) throws Throwable {  boolean isInitializingBean = bean instanceof InitializingBean;  if ((isInitializingBean)    && (((mbd == null) || (!(mbd      .isExternallyManagedInitMethod("afterPropertiesSet")))))) {   if (this.logger.isDebugEnabled()) {    this.logger      .debug("Invoking afterPropertiesSet() on bean with name '"        + beanName + "'");   }   //先调用afterPropertiesSet()进行初始化   if (System.getSecurityManager() != null) {    try {     AccessController.doPrivileged(       new PrivilegedExceptionAction(bean) {        public Object run() throws Exception {         ((InitializingBean) this.val$bean)           .afterPropertiesSet();         return null;        }       }, getAccessControlContext());    } catch (PrivilegedActionException pae) {     throw pae.getException();    }   } else {    ((InitializingBean) bean).afterPropertiesSet();   }  }    //然后调用InitMethod()进行初始化  if (mbd != null) {   String initMethodName = mbd.getInitMethodName();   if ((initMethodName == null)     || ((isInitializingBean) && ("afterPropertiesSet"       .equals(initMethodName)))     || (mbd.isExternallyManagedInitMethod(initMethodName)))    return;   invokeCustomInitMethod(beanName, bean, mbd);  } }

从这段源码可以得出以下结论:

spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中通过init-method指定,两种方式可以同时使用

实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖

先调用afterPropertiesSet,再执行 init-method 方法,如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法

3、@PostConstruct

通过 debug 和调用栈找到类InitDestroyAnnotationBeanPostProcessor, 其中的核心方法,即 @PostConstruct 方法调用的入口:

@Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());        try {            metadata.invokeInitMethods(bean, beanName);        }        catch (InvocationTargetException ex) {            throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());        }        catch (Throwable ex) {            throw new BeanCreationException(beanName, "Failed to invoke init method", ex);        }        return bean;    }

从命名上,我们就可以得到某些信息--这是一个BeanPostProcessor。BeanPostProcessor的postProcessBeforeInitialization是在Bean生命周期中afterPropertiesSet和init-method之前被调用的。另外通过跟踪,@PostConstruct方法的调用方式也是通过反射机制。

4、小结一下吧

spring bean的初始化执行顺序:构造方法 --> @PostConstruct注解的方法 --> afterPropertiesSet方法 --> init-method指定的方法。具体可以参考例子

afterPropertiesSet通过接口实现方式调用(效率上高一点),@PostConstruct和init-method都是通过反射机制调用

同理,bean销毁过程的顺序为:@PreDestroy > DisposableBean > destroy-method

不再展开,看源码就好

测试代码如下:

@Slf4jpublic class InitSequenceBean implements InitializingBean {    public InitSequenceBean() {        log.info("InitSequenceBean: construct");    }    @Override    public void afterPropertiesSet() throws Exception {        log.info("InitSequenceBean: afterPropertiesSet");    }    @PostConstruct    public void postConstruct() {        log.info("InitSequenceBean: postConstruct");    }    public void initMethod() {        log.info("InitSequenceBean: initMethod");    }}@Configurationpublic class SystemConfig {    @Bean(initMethod = "initMethod", name = "initSequenceBean")    public InitSequenceBean initSequenceBean() {        return new InitSequenceBean();    }}@Slf4jpublic class InitSequenceBeanTest extends ApplicationTests {    @Autowired    private InitSequenceBean initSequenceBean;    @Test    public void initSequenceBeanTest() {        log.info("Finish: {}", initSequenceBean.toString());    }}

以上就是使用spring容器在初始化Bean时前和后的操作是怎样的,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

方法 代码 接口 方式 测试 结果 容器 文件 注解 配置 源码 顺序 反射 运行 信息 入口 周期 就是 效率 是在 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 智能科技公司是互联网公司吗 互联网 科技公司 亿人帮互联网科技 互联网科技公司做什么 恒生科技互联网指数分析 银川新华互联网科技学校地址 天速互联网络科技有限公司 中国科技互联网公司收入 以后互联网后是啥科技 湖北码尼互联网科技有限公司电话 恒生互联网科技指数跳水 科技类公司包括互联网吗 无锡工业互联网科技有限公司 珠海东科互联网科技有限公司 互联网科技平台产品运营 银川新华互联网科技学校原画 互联网的科技体现在哪里 互联网科技对化妆品行业 互联网对科技影响 伍佰万互联网科技是干嘛的 上海挚品互联网科技有限公司 互联网的科技 互联网巨头科技公司 互联网科技大会 广州优美互联网科技 世界互联网科技公司市值排名 山东星卡互联网科技有限公司官网 互联网界的黑科技 广州智享互联网科技 互联网科技自媒体灵感
0