三种方式创建bean对象在springIOC容器中初始化、销毁阶段要调用的自定义方法
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容器中初始化、销毁阶段要调用的自定义方法的更多相关文章
- 于Unity3D动态创建对象和创建Prefab三种方式的原型对象
于Unity3D动态创建对象和创建Prefab三种方式的原型对象 u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject o ...
- sping练习,在Eclipse搭建的Spring开发环境中,使用工厂方式创建Bean对象,将创建的Bean对象输出到控制台。
相关 知识 >>> 相关 练习 >>> 实现要求: 在Eclipse搭建的Spring开发环境中,使用工厂方式创建Bean对象,将创建的Bean对象输出到控制台.要 ...
- Spring实例化Bean的三种方式及Bean的类型
1.使用类构造器实例化 [默认的类构造器] <bean id=“orderService" class="cn.itcast.OrderServiceBean"/ ...
- 为ScrollView增加圆角的三种方式,及自定义属性【在Linearlayout中新增ScrollView支持滚动 后续】
获取圆角的几种方案如下:方案一:通过shape来实现,给scrollView增加背景来实现方案二:通过自定义ScrollView,还要自定义属性,在dispatchDraw中不停的裁剪方案三:用And ...
- Android 三种方式实现自定义圆形页面加载中效果的进度条
转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=76872 一.通过动画实现 定义res/anim/loading.xml如 ...
- 阶段3 2.Spring_03.Spring的 IOC 和 DI_6 spring中bean的细节之三种创建Bean对象的方式
目前这里能调用是因为,在service的实现类里面,new了一个dao的对象 正常情况下 这里不应该是new一个对象,应该等于null或为空 设置为空侯再运行就会报错 出错的原因是这里为null 需要 ...
- 创建 Spring容器的三种方式
一.src路径下打包完在war包的classes层级下 1.Spring容器创建的三种方式 创建Bean容器之后创建对象: 其中第三种使用的是BeanFactory对象 2.spring通过配置文件用 ...
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
- java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService
前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...
随机推荐
- SCUT - 216 - 宝华科技树
https://scut.online/p/216 演员 把这个当成dp算了半天,各种姿势,好吧,就当练习一下树dp. 假如是每个节点的层数之和,按照dp[i][j]为从i点出发获得j科技的最小费用d ...
- Ruby下安装cocoapods
常规安装:(文末:特殊安装) 注: 1.Mac OS X EI Capitan 10.11中需要更改安装路劲: sudo gem install -n /usr/local/bin cocoapods ...
- mknod - 建立块专用或字符专用文件
总览 mknod [options] name {bc} major minor mknod [options] name p GNU 选项(缩写): [-m mode] [--help] [--ve ...
- md5sum - 计算检验MD5效验码
总览 (SYNOPSIS) ../src/md5sum [OPTION] [FILE]... ../src/md5sum [OPTION] --check [FILE] 描述 (DESCRIPTION ...
- PAT Advanced 1002 A+B for Polynomials (25 分)(隐藏条件,多项式的系数不能为0)
This time, you are supposed to find A+B where A and B are two polynomials. Input Specification: Each ...
- Codeforces 950 010子序列拆分 数列跳棋
A B a,b两个序列分成K段 每一段的值相等 #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset ...
- GUI学习之十七——QDoubleSpinBox学习总结
在上一章我总结了QSpinBox的使用方法,QSpinBox是用来操作整数或离散集合的,还有另外一种控件是用来操作浮点类数据的,就是QDoubleSpinBox. 一.描述 QDoubleSpinBo ...
- vue2.0 之 过渡动画transtion
过渡的类名: 在进入/离开的过渡中,会有 6 个 class 切换 (v 是前缀,name = v) v-enter:定义进入过渡的开始状态.在元素被插入时生效,在下一个帧移除. v-enter-ac ...
- java并发学习--第八章 JDK 8 中线程优化的新特性
一.新增原子类LongAdder LongAdder是JDK8中AtomicLong的增强工具类,它与AtomicLong最大的不同就是:在多线程场景下,LongAdder中对单一的变量进行拆分成多个 ...
- 如何用git将本地代码上传github
其实去年就用github了,但是毕竟也只是在上面搜索一些工作的难点和自我学习,自己都没有贡献过代码,觉得确实很low,知道今天自己用了2周左右的时间开发了 微信小程序,有了自己的贡献代码,所以想上传到 ...