spring init-method和destroy方法的使用

本文深入探讨了Spring框架中Bean的生命周期,包括初始化和销毁的方法。通过Java配置和JSR-250注解展示了如何定义init-method和destroy-method,以及在配置文件中设置这些方法的示例。

在项目中曾多次看到init-method和destroy方法的相关配置,今天特地具体的了解了一下,简单说说几种使用方法。

1、java形式的配置方式:

package com.fyf.service;

public class BeanCreateService {

    public void init(){
        System.out.println("init(),在BeanCreateService bean初始化完之后执行。");
    }

    public BeanCreateService(){
        super();
        System.out.println("BeanCreateService bean的初始化构造函数。");
    }

    public void destroy(){
        System.out.println("destroy(),在BeanCreateService bean销毁后执行。");
    }
}

2、-250的方式:

package com.fyf.service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class JSR250BeanCreateService {

    @PostConstruct
    public void init(){
        System.out.println("init(),在JSR250BeanCreateService bean初始化完之后执行。");
    }

    public JSR250BeanCreateService(){
        super();
        System.out.println("JSR250BeanCreateService bean的初始化构造函数。");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("destroy(),在JSR250BeanCreateService bean销毁后执行。");
    }
}

编写我们的配置bean:

package com.fyf.config;

import com.fyf.service.BeanCreateService;
import com.fyf.service.JSR250BeanCreateService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.fyf")
public class BeanConfig {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    BeanCreateService beanCreateService(){
        return new BeanCreateService();
    }

    @Bean
    JSR250BeanCreateService jsr250BeanCreateService(){
        return new JSR250BeanCreateService();
    }
}

最后编写一个测试类:

package com.fyf.controller;

import com.fyf.config.BeanConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestController {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
        //销毁bean
        context.close();
    }
}

 我们来看下运行的结果:

BeanCreateService bean的初始化构造函数。
init(),在BeanCreateService bean初始化完之后执行。
JSR250BeanCreateService bean的初始化构造函数。
init(),在JSR250BeanCreateService bean初始化完之后执行。
destroy(),在JSR250BeanCreateService bean销毁后执行。
destroy(),在BeanCreateService bean销毁后执行。
 

还有一种就是放在配置文件里的,大概是这样子的:

<!-- 配置初始化方法和销毁方法 -->                  
<bean id="person" class="com.fyf.service.BeanCreateService"  lazy-init="false" init-method="init" 
destroy-method="destory"></bean>

效果都是一样的。

 

 

 

 

 

<think> 首先,用户的问题是:“我想查找spring init-method的实现方式 请问spring init-method的实现方式”。用户正在询问Spring框架中init-method的实现方式。 从系统级指令中,我需要: - 使用$...$格式的行内数学表达式(但这个问题是关于编程的,可能没有数学表达式,所以如果相关才用)。 - 独立公式用$$...$$,但可能不适用。 - 使用中文回答。 - 生成相关问题。 - 在引用段落末尾添加引用标识,如[^1]。 用户提供了几个引用: - [^1]:描述了init-method在构造函数后被调用,destroy-method在销毁前调用。 - [^2]:比较了init-method、@PostConstructInitializingBean。 - [^3]:展示了使用@Bean注解定义initdestroy方法- [^4]:讨论了执行顺序。 - [^5]:提到了一段代码,展示了如何在配置中设置init-method。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题你的回答。” 但在对话历史中,上一次问题是快速排序的演示,没有直接相关。这个对话是独立的,所以我会基于当前问题引用回答。 关键点:用户想知道init-method的实现方式。这意味着Spring框架内部如何实现调用init-method。 从引用中: - [^5]给出了一个线索:在解析配置时,如果有INIT_METHOD_ATTRIBUTE(init-method属性),就设置到BeanDefinition中。 我需要构建一个清晰的回答: 1. **解释init-method是什么**:init-methodSpring框架中允许在Bean初始化后执行自定义方法的一种机制。 2. **实现方式**: -Spring的Bean生命周期中,当Bean实例化后,初始化阶段会调用指定的方法- 具体实现:在Spring的AbstractAutowireCapableBeanFactory类中,初始化时会检查BeanDefinition中是否有initMethodName设置。 - 如果设置了initMethodName,框架会通过反射调用该方法- 引用[^5]提到代码片段:在解析XML或配置时处理init-method属性。 3. **顺序与其他机制的对比**:引用[^4]提到执行顺序,可能需要简要提及,但焦点是实现方式。 4. **如何使用**:简要展示如何配置,如引用[^3]中的例子。 回答结构: - 开头解释init-method- 描述实现机制:Spring在Bean初始化阶段查找并调用指定的方法- 提及底层代码:如AbstractAutowireCapableBeanFactory中的initializeBean方法- 添加引用标识:在描述基于引用的内容时加[^n]。 - 生成相关问题。 确保语言是中文。 生成相关问题: - 类似于示例,如: 1. init-method@PostConstruct的区别是什么? 2. 如何配置init-method在XML中? 3. init-method的执行顺序如何控制? 最终回答: - 清晰、逐步解释。 - 结尾添加相关问题。 </think> ### Spring init-method 的实现方式 在 Spring 框架中,`init-method` 是一种用于指定 Bean 初始化后执行自定义逻辑的机制。它允许开发人员在 Bean 完全构造后(即构造函数调用完成后),通过配置式的方式触发一个特定的方法。这种方式解耦了 Bean 的初始化逻辑,使其更易于维护。以下我将逐步解释 `init-method` 的实现方式,基于 Spring 的内部机制提供的引用。 #### 1. **核心实现机制** Spring 在 Bean 的生命周期管理阶段实现 `init-method`,主要通过 BeanDefinition Bean 工厂类来处理: - **BeanDefinition 存储**:当 Spring 解析配置文件(如 XML)或注解时(如 `@Bean`),如果定义了 `init-method` 属性,它会将这个方法的名称存储到 BeanDefinition 对象中。这发生在配置加载阶段,例如在 XML 解析时: ```java // 类似引用[5]中的代码片段:解析 init-method 属性 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); if (!"".equals(initMethodName)) { bd.setInitMethodName(initMethodName); // 设置到 BeanDefinition } } ``` 这里,`INIT_METHOD_ATTRIBUTE` 对应配置中的 `init-method` 属性名,Spring 将其保存到 `bd`(BeanDefinition 实例)中[^5]。 - **初始化阶段调用**:在 Bean 实例化后,Spring 的核心类 `AbstractAutowireCapableBeanFactory` 负责初始化过程。具体在 `initializeBean` 方法中,它会检查 BeanDefinition 中是否有 `initMethodName`: - 如果设置了 `initMethodName`,Spring 通过 Java 反射机制调用该方法- 调用顺序在构造函数之后、依赖注入完成后,确保 Bean 处于有效状态[^1][^4]。 - 例如,伪代码简化: ```java protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) { // ... 其他初始化逻辑(如后置处理器) if (mbd.getInitMethodName() != null) { invokeCustomInitMethod(bean, mbd.getInitMethodName()); // 反射调用 init-method } return bean; } ``` #### 2. **与其他初始化机制的对比顺序** `init-method` 是 Spring 提供的多种初始化方式之一,与其他机制(如 `InitializingBean` 接口或 `@PostConstruct` 注解)共存: - **执行顺序**:根据引用[^4],Bean 初始化的标准顺序是: 1. 构造函数调用。 2. 依赖注入完成。 3. `@PostConstruct` 方法(如果使用了 JSR-250 注解)。 4. `InitializingBean` 的 `afterPropertiesSet` 方法。 5. 配置的 `init-method` 方法。 这意味着 `init-method` 总是在最后执行,确保所有前置初始化已完成[^2][^4]。 - **优势**:`init-method` 通过 XML 或 Java 配置声明,与 Bean 类解耦(不强制实现接口),提高了代码灵活性。相比 `@PostConstruct`(需要注解在方法上),它更适用于外部配置驱动的场景[^2][^3]。 #### 3. **配置示例** `init-method` 可以通过 XML 或注解配置: - **XML 配置**: ```xml <bean id="personBean" class="com.example.Person" init-method="init" destroy-method="destroy"/> ``` 这里,`init` 是 Person 类中定义的方法Spring 在初始化后自动调用它[^3]。 - **注解配置**(使用 `@Bean`): ```java @Configuration public class AppConfig { @Bean(initMethod = "init", destroyMethod = "destroy") public Person person() { return new Person(); } } ``` 在 Person 类中定义 `public void init()` 方法作为初始化逻辑[^3]。 #### 4. **适用场景注意事项** - **典型用途**:加载初始化数据、资源连接(如数据库连接池启动)或状态验证,通常在构造函数后需要额外设置时使用[^3]。 - **注意事项**: - 方法必须是 public void 无参方法,否则 Spring 会抛出异常。 - 如果同时定义了多个初始化机制(如 `init-method` `@PostConstruct`),它们会按顺序执行,但推荐保持单一机制以避免复杂性[^4]。 - 销毁阶段的 `destroy-method` 实现类似,在 Bean 销毁前调用,处理资源释放[^1]。 总之,Spring `init-method` 的实现依赖于 BeanDefinition 存储方法反射调用,核心在 `AbstractAutowireCapableBeanFactory` 类中完成。这种机制设计灵活,是 Spring Bean 生命周期管理的重要组成部分[^1][^5]。 ### 相关问题 1. init-method @PostConstruct 的区别以及如何选择? 2. 如何在 Spring XML 配置中正确使用 init-method? 3. Spring Bean 的生命周期中,init-method 的执行顺序如何与其他钩子交互?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值