1. 使用@Bean注解定义initMethod和destroyMethod

所谓initMethod和destroyMethod,是指在springIOC容器中,对于bean对象执行到初始化阶段和销毁阶段所调用的方法,其并不是初始化方法和销毁方法本身。

对于单例模式,initMethod会在创建容器时,构造方法、属性赋值方法完成之后调用,destroyMethod会在关闭容器之后调用;

对于原型模式,initMethod会在每次获取bean对象时,构造方法、属性赋值方法完成之后调用,而destroyMethod则不会调用,换句话说,对于多实例bean,springIOC容器只负责创建,不负责销毁。

/**
* 使用@Bean注解的方式定义initMethod和destroyMethod
* initMethod方法:
* 是springIOC容器执行到初始化bean对象阶段时调用的方法,并不是初始化bean对象方法本身
* 对于单实例模式,是在创建容器之后执行,只执行一次
* 对于多实例模式,是在获取bean对象时执行,每获取一次,则执行一次
* destroyMethod方法:
* 是springIOC容器执行到销毁bean对象阶段时调用的方法,并不是销毁bean对象方法本身
* 对于单例模式,是在关闭容器之前执行
* 对于多实例模式,ICO容器不负责销毁对象,因此销毁方法也不负责执行
*/
@Configuration
public class LifeBeanConfig { /**
* 单例模式注册Car
* bean初始化阶段调用onInit方法
* bean销毁阶段调用onDestroy方法
*/
@Bean(value = "singleCar", initMethod = "onInit", destroyMethod = "onDestroy")
@Scope(value = SCOPE_SINGLETON)
public Car singleCar() {
//调用无参构造器创建Car对象
Car car = new Car();
//设置属性
car.setMake("BMW X5");
car.setPrice(600000);
//返回Car对象
return car;
} /**
* 多例模式注册Car
* bean初始化阶段调用onInit方法
* bean销毁阶段调用onDestroy方法
*/
@Bean(value = "multiCar", initMethod = "onInit", destroyMethod = "onDestroy")
@Scope(value = SCOPE_PROTOTYPE)
public Car multiCar() {
//调用无参构造器创建Car对象
Car car = new Car();
//设置属性
car.setMake("BMW X5");
car.setPrice(600000);
//返回Car对象
return car;
}
}

测试单例模式

    /**
* 测试使用单实例@Bean注解定义初始化和销毁阶段调用的方法
*/
@Test
public void test1() {
//创建springIOC容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeBeanConfig.class);
System.out.println("创建springIOC容器完成...");
//从容器中获取bean对象
Car car = (Car) applicationContext.getBean("singleCar");
System.out.println("获取bean对象完成...");
//关闭springIOC容器
((AnnotationConfigApplicationContext)applicationContext).registerShutdownHook();
System.out.println("关闭springIOC容器完成...");
}

测试结果

正在调用Car的无参构造方法……
正在为Car的make属性赋值……
正在为Car的price属性赋值……
car正在初始化……
创建springIOC容器完成...
获取bean对象完成...
关闭springIOC容器完成...
car正在销毁……

从测试结果看出,对于单例模式,初始化是在创建springIOC容器时,在执行完构造方法和属性赋值方法之后执行的,销毁是在执行关闭容器方法之后、容器真正关闭之前执行的

测试原型模式

    /**
* 测试使用多实例@Bean注解定义初始化和销毁阶段调用的方法
*/
@Test
public void test2() {
//创建springIOC容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeBeanConfig.class);
System.out.println("创建springIOC容器完成...");
//从容器中获取bean对象
Car car = (Car) applicationContext.getBean("multiCar");
System.out.println("获取bean对象完成...");
//关闭springIOC容器
((AnnotationConfigApplicationContext)applicationContext).registerShutdownHook();
System.out.println("关闭springIOC容器完成...");
}

测试结果

创建springIOC容器完成...
正在调用Car的无参构造方法……
正在为Car的make属性赋值……
正在为Car的price属性赋值……
car正在初始化……
获取bean对象完成...
关闭springIOC容器完成...

从测试结果可以看出,对于原型模式,初始化是在获取bean对象时,在执行完构造方法和属性赋值方法之后执行的,没有销毁过程,即使容器关闭也并没有销毁。

2. 通过实现spring提供的接口,定义初始化阶段和销毁阶段需要执行的方法

在bean类上实现InitializingBean,其实现方法afterPropertiesSet会在初始化阶段完成了构造方法和属性赋值之后被执行,相当于上述initMethod;

同理,在bean类上实现DisposableBean接口,其实现方法destroy为在销毁阶段关闭了容器之后被执行,相当于上述destroyMethod。

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; /**
* bean类
* 通过实现spring提供的接口,定义在初始化和销毁阶段要调用的方法
*/
public class Bus implements InitializingBean, DisposableBean { /**
* 初始化阶段,在完成属性赋值方法之后调用的方法
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("正在对bus对象进行初始化...");
} /**
* 销毁阶段,在关闭容器之后调用的方法
* @throws Exception
*/
@Override
public void destroy() throws Exception {
System.out.println("正在对bus对象进行销毁...");
} ...
}

3. 通过加JSR-250规范的注解,定义初始化阶段和销毁阶段需要执行的方法

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; /**
* bean类
* 通过加JSR-250注解,定义在初始化和销毁阶段要调用的方法
*/
public class Bus { //初始化阶段调用的方法
@PostConstruct
public void postConstruct() {
System.out.println("postConstruct...");
} //销毁阶段调用的方法
@PreDestroy
public void preDestroy() {
System.out.println("preDestroy...");
} ...
}

那么,在同一个bean类上定义initMethod/destroyMethod方法、实现InitializingBean/Disposable接口、加PostContruct/PreDestroy注解,这三组方法的执行顺序如何?经测试,JSR-250注解先执行,spring接口第二个执行,bean注解声明的initMethod/destroyMethod最后执行。

package cn.monolog.entity;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; /**
* bean类
* 分别通过三种方式定义初始化阶段和销毁阶段要调用的方法
*/
public class Bus implements InitializingBean, DisposableBean { //初始化阶段调用的方法,需要在配置类的@Bean注解中将该方法定义为initMethod
public void onInit() {
System.out.println("initMethod...");
} //销毁阶段调用的方法,需要在配置类的@Bean注解中将该方法定义为destroyMethod
public void onDestroy() {
System.out.println("destroyMethod...");
} /**
* 初始化阶段,在完成属性赋值方法之后调用的方法
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean...");
} /**
* 销毁阶段,在关闭容器之后调用的方法
* @throws Exception
*/
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean...");
} //初始化阶段调用的方法
@PostConstruct
public void postConstruct() {
System.out.println("postConstruct...");
} //销毁阶段调用的方法
@PreDestroy
public void preDestroy() {
System.out.println("preDestroy...");
} ...
}
@Test
public void test() {
//创建springIOC容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeBeanConfig.class);
System.out.println("创建springIOC容器完成...");
//关闭springIOC容器
((AnnotationConfigApplicationContext)applicationContext).registerShutdownHook();
System.out.println("关闭springIOC容器完成...");
}

测试结果:

正在调用bus的无参构造方法...
正在对bus的make属性进行赋值...
正在对bus的price属性进行赋值...
postConstruct...
InitializingBean...
initMethod...
创建springIOC容器完成...
关闭springIOC容器完成...
preDestroy...
DisposableBean...
destroyMethod...

三种方式创建bean对象在springIOC容器中初始化、销毁阶段要调用的自定义方法的更多相关文章

  1. 于Unity3D动态创建对象和创建Prefab三种方式的原型对象

    于Unity3D动态创建对象和创建Prefab三种方式的原型对象 u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject o ...

  2. sping练习,在Eclipse搭建的Spring开发环境中,使用工厂方式创建Bean对象,将创建的Bean对象输出到控制台。

    相关 知识 >>> 相关 练习 >>> 实现要求: 在Eclipse搭建的Spring开发环境中,使用工厂方式创建Bean对象,将创建的Bean对象输出到控制台.要 ...

  3. Spring实例化Bean的三种方式及Bean的类型

    1.使用类构造器实例化  [默认的类构造器] <bean id=“orderService" class="cn.itcast.OrderServiceBean"/ ...

  4. 为ScrollView增加圆角的三种方式,及自定义属性【在Linearlayout中新增ScrollView支持滚动 后续】

    获取圆角的几种方案如下:方案一:通过shape来实现,给scrollView增加背景来实现方案二:通过自定义ScrollView,还要自定义属性,在dispatchDraw中不停的裁剪方案三:用And ...

  5. Android 三种方式实现自定义圆形页面加载中效果的进度条

    转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=76872 一.通过动画实现 定义res/anim/loading.xml如 ...

  6. 阶段3 2.Spring_03.Spring的 IOC 和 DI_6 spring中bean的细节之三种创建Bean对象的方式

    目前这里能调用是因为,在service的实现类里面,new了一个dao的对象 正常情况下 这里不应该是new一个对象,应该等于null或为空 设置为空侯再运行就会报错 出错的原因是这里为null 需要 ...

  7. 创建 Spring容器的三种方式

    一.src路径下打包完在war包的classes层级下 1.Spring容器创建的三种方式 创建Bean容器之后创建对象: 其中第三种使用的是BeanFactory对象 2.spring通过配置文件用 ...

  8. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  9. java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

随机推荐

  1. 字符串hash 模板

    typedef long long ll; typedef unsigned long long ull; #define maxn 1005 struct My_Hash { ull ; ull p ...

  2. Centos 修改当前路径显示为全路径

    1.修改显示全路径: vim /etc/bashrc 找到[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\ ...

  3. spark 在启动的时候出现JAVA_HOME not set

    解决方法:在sbin目录下的spark-config.sh 中添加对应的jdk 路径,然后使用scp -r 命令复制到各个worker节点

  4. UDP即时小通信

    package 第十二章; import java.io.IOException; import java.net.*; public class UDPServer { /*** * * @para ...

  5. Quartus 中调用modelsim的流程及*.vt或*.vht自动生成

    一.自动生成验证程序testbench的方法,setting-EDA Tool->simylation->选择对应的语言(verilog对应*.vt,VHDL对应*.vht)process ...

  6. mongo 数据库操作

    启动和关闭数据库 启动 # mongodb 默认使用执行 mongod 命令所处的盘的根目录下  /data/db 作为自己的数据存储目录 #   所以在第一次执行该命令之前先自己动手新建一个  /d ...

  7. python3:类和实例

    面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可 ...

  8. java 中的编码

    1.1字节=8位,1024字节=1KB2.16进制0x12345678,其二进制为00010010 00110100 01010110 01111000共4字节3.字节序:两个或多个字节存放的先后顺序 ...

  9. php内置函数分析之strpos()

    PHP_FUNCTION(strpos) { zval *needle; zend_string *haystack; char *found = NULL; ]; zend_long offset ...

  10. 组件通信 $ref

    (1)放在dom上表示获取当前dom元素, (2)放到组件上表示获取当前组件实例 (3)在v-for中获取的是集合 <!DOCTYPE html> <html lang=" ...