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. javascript xml转json

    1.代码 //加载xml数据 function loadXml(str) { if (str == null) { return null; } var doc = str; try{ doc = c ...

  2. 剑指offer-二维数组中的查找-数组-python

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  3. ASP.NET CORE 2.2 MVC 学习

    百度云链接:https://pan.baidu.com/s/1_iSy3wq4Jegr6j_AH9nobA 提取码:n152

  4. CentOS7部署CDH6.0.1大数据平台

    Cloudera’s Distribution Including Apache Hadoop,简称“CDH”,基于Web的用户界面,支持大多数Hadoop组件,包括HDFS.MapReduce.Hi ...

  5. 008-kvm虚拟化管理平台WebVirtMgr部署-完整记录(1)

    公司机房有一台2U的服务器(64G内存,32核),由于近期新增业务比较多,测试机也要新增,服务器资源十分有限.所以打算在这台2U服务器上部署kvm虚拟化,虚出多台VM出来,以应对新的测试需求. 当KV ...

  6. 大数据数据库HBase(二)——搭建与JavaAPI

    一.搭建 1.选择一台没有ZK的机器(HBase自带ZK,可能会导致冲突) 2.选择版本2.0.5的HBase 3.解压HBase2.0.5 4.配置HBase的HBASE_HOME和path 5.修 ...

  7. ubuntu不能登陆

    开机按shift,找到之前的内核版本或者recovery 安装vmtools 报错Not enough free space to extract VMwareTools 解决办法:将此文件夹复制到另 ...

  8. python dict字典常用操作

    字典的特性:key唯一无序 '''特性:key唯一:无序''' info = { 'stu1101': "安徽", 'stu1102': "北京", 'stu1 ...

  9. pymysql基本操作

    https://www.cnblogs.com/woider/p/5926744.html https://www.runoob.com/python3/python3-mysql.html 注意: ...

  10. python数组中在某一元素前插入数据

    # 已知有一个已经排好序的数组.要求是,有一个新数据项,要求按原来的规律将它插入数组中. a=[1,2,3,4,5,6,7,8,9]num=int(input("input num:&quo ...