@Bean 生命周期
bean生命周期:
实例bean
1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;
2.根据配置情况调用Bean构造函数或工厂方法实例化Bean;
3.如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化Bean之后,调用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的对象进行一些"梳妆打扮";
4.如果Bean配置了属性信息,容器在这一步着手将配置值设置到Bean对应的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法;
**
**
初始化和使用bean
1:BeanNameAware的setBeanName():
如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
2:BeanFactoryAware的setBeanFactory():
如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
3:BeanPostProcessors的ProcessBeforeInitialization()
如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。
4:initializingBean的afterPropertiesSet():
如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法
5:Bean定义文件中定义init-method:
可以在Bean定义文件中使用"init-method"属性设定方法名称例如:
如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法
6:BeanPostProcessors的ProcessaAfterInitialization()
如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法
BeanPostProcessor后处理器定义了两个方法:
** 其一是postProcessBeforeInitialization()在第8步调用;其二是Object postProcessAfterInitialization(Object bean, String beanName)方法,这个方法在此时调用,容器再次获得对Bean进行加工处理的机会;**
** 如果在中指定Bean的作用范围为scope="prototype",将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不再管理这个Bean的生命周期。如果作用范围设置为scope="singleton",则将Bean放入到Spring IoC容器的缓存池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理;**
销毁bean
此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉
1:DisposableBean的destroy()
在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法
2:Bean定义文件中定义destroy-method
在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称,例如:
如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessors的ProcessBeforeInitialization()及之后的流程。
代码:
package com.company; import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import java.beans.PropertyDescriptor; public class Main{
public static void main(String[] args) {
//①下面两句装载配置文件并启动容器
Resource res = new ClassPathResource("beans.xml");
BeanFactory bf = new XmlBeanFactory(res); //②向容器中注册MyBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor()); //③向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(
new MyInstantiationAwareBeanPostProcessor());
//④第一次从容器中获取worker,将触发容器实例化该Bean,这将引发Bean生命周期方法的调用。
Worker worker1 = (Worker)bf.getBean("worker");
System.out.println("第一次从容器中获取worker");
worker1.printInfo();
System.out.println("修改第一次从容器中获取worker的workType");
worker1.setWorkType("正式工");
System.out.println("第一次从容器中获取worker(修改过后的)");
worker1.printInfo();
//⑤第二次从容器中获取worker,直接从缓存池中获取
System.out.println("第二次从容器中获取worker");
Worker worker2= (Worker)bf.getBean("worker");
worker2.printInfo();
//⑥查看worker1和worker2是否指向同一引用
System.out.println("查看worker1和worker2是否指向同一引用 ");
System.out.println("worker1==worker2:"+(worker1==worker2));
//⑦关闭容器
((XmlBeanFactory)bf).destroySingletons();
} }
//①管理Bean生命周期的接口
class Worker implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean {
private String name;
private String workType;
private int salary; public BeanFactory beanFactory;
private String beanName; public void Worker(){
System.out.println("调用worker()构造函数");
} public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWorkType() {
return workType;
}
public void setWorkType(String workType) {
this.workType = workType;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void printInfo() {
System.out.println("name:" + name + ";workType:" + workType + ";salary:"
+ salary);
}
//⑤DisposableBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("----------------销毁bean----------------------");
System.out.println("调用DisposableBean.destroy()。"); }
//④InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()。"); }
//③BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("----------------初始化bean----------------------");
System.out.println("调用BeanNameAware.setBeanName()。");
this.beanName = arg0; }
//②BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()。");
this.beanFactory = arg0;
} //⑥通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("调用init-method所指定的myInit(),将salary设置为600。");
this.salary = 600;
} //⑦通过<bean>的destroy-method属性指定的销毁方法
public void myDestroy() {
System.out.println("调用destroy-method所指定的myDestroy()。");
} } class MyBeanPostProcessor implements BeanPostProcessor { @Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if(beanName.equals("worker")){
Worker worker = (Worker)bean;
if(worker.getWorkType() == null){
System.out.println("调用BeanPostProcessor.postProcess AfterInitialization(), getWorkType为空,设置为默认临时工");
worker.setWorkType("临时工");
}
}
return bean;
} @Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if(beanName.equals("worker")){
Worker worker = (Worker)bean;
if(worker.getSalary() >= 1000){
System.out.println("调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。");
worker.setSalary(800);
}
}
return bean;
} } class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
// ①接口方法:在实例化Bean前进行调用
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out.println("----------------实例化bean----------------------");
// ①-1仅对容器中worker Bean进行处理
if ("worker".equals(beanName)) {
System.out
.println("InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation");
}
return null;
} // ②接口方法:在实例化Bean后调用
public boolean postProcessAfterInstantiation(Object bean, String beanName)
throws BeansException {
// ②-1仅对容器中car Bean进行处理
if ("worker".equals(beanName)) {
System.out
.println("InstantiationAware BeanPostProcessor.postProcess AfterInstantiation");
}
return true;
} // ③接口方法:在设置某个属性时调用
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException { // ③-1仅对容器中wroker Bean进行处理,还可以通过pdst入参进行过滤,
// 仅对car的某个特定属性时进行处理。
if ("worker".equals(beanName)) {
System.out
.println("Instantiation AwareBeanPostProcessor.postProcess PropertyValues");
}
return pvs;
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="worker" class="com.company.Worker"
init-method="myInit"
destroy-method="myDestroy"
p:name="小强"
p:salary="1000"
/>
</beans>
Result:
----------------实例化bean----------------------
InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation
InstantiationAware BeanPostProcessor.postProcess AfterInstantiation
Instantiation AwareBeanPostProcessor.postProcess PropertyValues
----------------初始化bean----------------------
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将salary设置为600。
调用BeanPostProcessor.postProcess AfterInitialization(), getWorkType为空,设置为默认临时工
第一次从容器中获取worker
name:小强;workType:临时工;salary:600
修改第一次从容器中获取worker的workType
第一次从容器中获取worker(修改过后的)
name:小强;workType:正式工;salary:600
第二次从容器中获取worker
name:小强;workType:正式工;salary:600
查看worker1和worker2是否指向同一引用
worker1==worker2:true
----------------销毁bean----------------------
调用DisposableBean.destroy()。
调用destroy-method所指定的myDestroy()。
http://www.kancloud.cn/evankaka/springlearning/119661
http://www.imooc.com/article/19449
https://my.oschina.net/guanhe/blog/1408505
http://blog.csdn.net/mack415858775/article/details/47721909
https://zhuanlan.zhihu.com/p/25459839
https://muyinchen.github.io/2017/08/23/Spring5%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90-@Autowired/
http://www.shangyang.me/2017/04/05/spring-core-container-sourcecode-analysis-annotation-autowired/
@Bean 生命周期的更多相关文章
- Spring之BeanFactory及Bean生命周期
1.spring通过BeanFactory灵活配置.管理bean,Spring对管理的bean没有任何特别的要求,完全支持对POJO的管理: 2.BeanFactory有个ApplicationCon ...
- Bean生命周期及BeanFactory
1.spring通过BeanFactory灵活配置.管理bean,Spring对管理的bean没有任何特别的要求,完全支持对POJO的管理: 2.BeanFactory有个ApplicationCon ...
- Spring Bean配置默认为单实例 pring Bean生命周期
Bean默认的是单例的. 如果不想单例需要如下配置:<bean id="user" class="..." scope="singleton&q ...
- Spring Bean 生命周期2
在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象使用Sin ...
- Spring bean 生命周期验证
一.从源码注释看bean生命周期 从JDK源码上看,BeanFactory实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为: 1.BeanNameAware s ...
- Spring:Bean生命周期
关于Bean生命周期,我在网上找了两张图: 图1: 图2: 总结起来就是: Bean构建: Bean对象创建 > @Autowired | @Resource> @PostConstruc ...
- Spring事务,Bean生命周期
一.事务相关: 1.Spring事务基于Spring AOP切面编程: 2.AOP基于代理模式,得到需要开启事务的代码的代理对象: 3.而没有开启事务的Service方法里调用了开启事务 @Trans ...
- 【不懂】spring bean生命周期
完整的生命周期(牢记): 1.spring容器准备 2.实例化bean 3.注入依赖关系 4.初始化bean 5.使用bean 6.销毁bean Bean的完整生命週期可以認為是從容器建立初始化Bea ...
- spring(二、bean生命周期、用到的设计模式、常用注解)
spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...
- spring bean 生命周期和 ? 作用域? spirng bean 相互依赖? jvm oom ? jvm 监控工具? ThreadLocal 原理
1. spring bean 生命周期 1. 实例化一个bean ,即new 2. 初始化bean 的属性 3. 如果实现接口 BeanNameAware ,调用 setBeanName 4. Bea ...
随机推荐
- Linux更换jdk版本,java -version还是原来的版本问题
服务器上默认安装版本是: 使用jenkins最新的安装包 2.73.1,启动报错52.0!需要使用1.8进行启动. 两种方式,要么tomcat直接指定,要么修改环境变量,这里我使用修改安装java版本 ...
- Mac - iPhone屏幕录制
1. Mac电脑屏幕录制 1.1 文件->新建屏幕录制 1.2 点击红色按钮 1.3 截取需要录制的屏幕部分,点击开始录制 1.4 点击工具栏的停止按钮,停止录制 1.5 然后会 ...
- Mac/Xcode - 开发技巧快捷键
Xcode是iPhone和iPad开发者用来编码或者开发iOS app的IDE.Xcode有很多小巧但很有用的功能,很多时候我们可能没有注意到它们,也或者我们没有在合适的水平使用这些功能简化我们的iO ...
- intelliij jdea灰色文件处理办法
- Windows下Git免密码pull&push
Windows下Git在使用http方式的时候clone,pull,push需要输入用户名及密码,通过以下设置可以免密码 在用户文件夹创建文件.git-credentials内容如下 https:// ...
- CodeForces 651 C Watchmen
C. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...
- spring boot tomcat 线程数 修改初始线程数 统计性能 每百次请求耗时
[root@f java]# tail -30 nohup.outsearchES-TimeMillisSpent:448P->1602@fT->http-nio-8080-exec-3t ...
- F(N)---hdu2802(寻找循环节)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2802 f[1] = 1; f[2] = 7; f[n] = (f[n-2] - (n-1)*(n-1) ...
- python模拟websocket握手过程中计算sec-websocket-accept
背景 以前,很多网站使用轮询实现推送技术.轮询是在特定的的时间间隔(比如1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给浏览器.轮询的缺点很明显,浏览器需要不断的向服 ...
- day14(编码实战-用户登录注册)
day14 案例:用户注册登录 要求:3层框架,使用验证码 功能分析 注册 登录 1.1 JSP页面 regist.jsp 注册表单:用户输入注册信息: 回显错误信息:当注册失败时,显示错误信 ...