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 生命周期的更多相关文章

  1. Spring之BeanFactory及Bean生命周期

    1.spring通过BeanFactory灵活配置.管理bean,Spring对管理的bean没有任何特别的要求,完全支持对POJO的管理: 2.BeanFactory有个ApplicationCon ...

  2. Bean生命周期及BeanFactory

    1.spring通过BeanFactory灵活配置.管理bean,Spring对管理的bean没有任何特别的要求,完全支持对POJO的管理: 2.BeanFactory有个ApplicationCon ...

  3. Spring Bean配置默认为单实例 pring Bean生命周期

    Bean默认的是单例的. 如果不想单例需要如下配置:<bean id="user" class="..." scope="singleton&q ...

  4. Spring Bean 生命周期2

    在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象使用Sin ...

  5. Spring bean 生命周期验证

    一.从源码注释看bean生命周期 从JDK源码上看,BeanFactory实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为: 1.BeanNameAware s ...

  6. Spring:Bean生命周期

    关于Bean生命周期,我在网上找了两张图: 图1: 图2: 总结起来就是: Bean构建: Bean对象创建 > @Autowired | @Resource> @PostConstruc ...

  7. Spring事务,Bean生命周期

    一.事务相关: 1.Spring事务基于Spring AOP切面编程: 2.AOP基于代理模式,得到需要开启事务的代码的代理对象: 3.而没有开启事务的Service方法里调用了开启事务 @Trans ...

  8. 【不懂】spring bean生命周期

    完整的生命周期(牢记): 1.spring容器准备 2.实例化bean 3.注入依赖关系 4.初始化bean 5.使用bean 6.销毁bean Bean的完整生命週期可以認為是從容器建立初始化Bea ...

  9. spring(二、bean生命周期、用到的设计模式、常用注解)

    spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...

  10. spring bean 生命周期和 ? 作用域? spirng bean 相互依赖? jvm oom ? jvm 监控工具? ThreadLocal 原理

    1. spring bean 生命周期 1. 实例化一个bean ,即new 2. 初始化bean 的属性 3. 如果实现接口 BeanNameAware ,调用 setBeanName 4. Bea ...

随机推荐

  1. 使用as3crypto在Flex中实现AES加密

    要在Flex中实现AES加密,可以通过as3crypto实现.但是as3crypto本身的用法比较复杂,一般是封装一下再调用. 下面是9RIA上的一篇文章给出的一个实现,使用中稍感不方便(见注释): ...

  2. Appium中长按按钮操作

    在一次项目中,appium要对某个按钮进行长按操作(大于2s),类似拍微信小视频,参考网上长按视频会报错 action1 = TouchActions(self.driver) el = self.d ...

  3. 使用SSH工具连接到MySQL

    在SSH中查看MySQL数据信息 格式为:mysql -h主机地址 -u用户名 -p用户密码 -P端口号 -D数据库名称 例如: mysql -uroot -p123456 -h192.168.1.1 ...

  4. 网络下载功能实现(downloader ) ---- HTML5+

    模块:downloader Downloader模块管理网络文件下载任务,用于从服务器下载各种文件,并支持跨域访问操作.通过plus.downloader获取下载管理对象.Downloader下载使用 ...

  5. MyBatis DAO层传递参数到mapping.xml 几种方式

    Dao层传递参数到mapping.xml文件的几种方式:(Mybatis传值总结) 第一种:传递单个参数 Dao层Code片段: /** * 根据articleId查询XXXX详情. * * @par ...

  6. supervisor安装篇

    服务器环境: [root@kafka60 supervisor-]# uname -a Linux kafka60 -.el6.x86_64 # SMP Tue May :: UTC x86_64 x ...

  7. Tomcat部署静态网站

    公司架构:公司架构有5套,主机都是阿里云的ecs,基本上都是SLB做前端负载均衡,后端Tomcat,后接RDS数据库. 业务需求:需要将公司现有网站指向一个二级域名,建立一个新的静态网站,将域名指向现 ...

  8. CentOS7.2升级默认yum安装的php版本

    CentOS7.2yum安装php默认版本为5.4,可以升级通过yum安装更高版本 设置yum源 rpm -Uvh https://mirror.webtatic.com/yum/el7/webtat ...

  9. ar的主流算法

    基于无标志AR:代表作是PTAM/M,Mixare,将是AR未来的发展方向 跟踪技术可以大致分成两大类,一类是基于特征的跟踪(Feature Based Tracking),比如通过跟踪从输入图像中抽 ...

  10. drop user ora-604 ora-54

    SQL> drop user EFMIS_87_LK cascade;drop user EFMIS_87_LK cascade*ERROR at line 1:ORA-00604: error ...