Spring (init-method和destroy-method )

本文详细介绍了如何在 Spring IoC 容器中配置和使用 Bean,包括初始化方法 init_xx 和析构方法 end 的应用,以及如何通过配置文件实现 Bean 的生命周期管理。

转自:http://www.blogjava.net/cmzy/archive/2008/07/29/218059.html

  1. /**
  2. *
  3. */
  4. packageioc.test;
  5. /**
  6. *@authorzhangyong
  7. *
  8. */
  9. publicclassAnimal{
  10. privateStringname;
  11. privateintage;
  12. publicStringspeak(){
  13. return"我的名字:"+this.name+",我的年龄:"+this.age;
  14. }
  15. publicvoidinit_xx()throwsException{
  16. System.out.println("初始化方法start()正在运行!");
  17. }
  18. publicvoidend()throwsException{
  19. System.out.println("析构方法end()正在运行!");
  20. }
  21. //Geter和Seter省略
  22. }

配置文件中配置好bean,并为其指定响应的预处理方法和析构方法:

这里的init_xx方法在实例化与依赖注入之前被调用,end方法在销毁之前调用

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beans
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  7. <beanid="animal"class="ioc.test.Animal"init-method="init_xx"destroy-method="end">
  8. <propertyname="age"value="5"></property>
  9. <propertyname="name"value="猪"></property>
  10. </bean>
  11. </beans>

创建含有主方法的测试类,代码如下:

  1. /**
  2. *
  3. */
  4. packageioc.test;
  5. importorg.springframework.context.support.AbstractApplicationContext;
  6. importorg.springframework.context.support.ClassPathXmlApplicationContext;
  7. /**
  8. *@authorzhangyong
  9. *
  10. */
  11. publicclassTestMain{
  12. publicstaticvoidmain(String[]args){
  13. AbstractApplicationContextac=newClassPathXmlApplicationContext("applicationContext.xml");
  14. //注册容器关闭钩子,才能关掉容器,调用析构方法
  15. ac.registerShutdownHook();
  16. Animalanimal=ac.getBean("animal",Animal.class);
  17. System.out.println(animal.speak());
  18. }
  19. }

运行主类,结果如下:


需要注意的是:要看到析构方法的输出,也必须要注册关闭钩子。

<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 的执行顺序如何与其他钩子交互?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值