Spring Bean的作用域和生命周期
Spring中5种作用域
在Spring配置Bean时, 可以通过设置scope属性来定义Bean的作用域, 按照scope的值来分, Bean的作用域分为以下几种:
- [基本作用域]singeton: 单例模式(默认方式), 每次返回同一个对象实例. 通过设置其 lazy-init参数可以设置是否延迟生成对象, 并将该对象存储在内部的ConcurrentHashMap中.
- [基本作用域]prototype: 原型模式, 每次都返回一个新的对象实例. 每次获取时才回去创建该对象.
- [Spring的Web作用域]request: 同一次请求返回同一个对象实例.
- [Spring的Web作用域]session: 同一次会话返回同一个对象实例.
- [Spring的Web作用域]global-session: 所有会话返回同一个对象实例.
基本作用域的使用
需要引入spring-core, spring-bean
public class ScopeDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Scope.xml");
System.out.println("singleton: " + (context.getBean(SingetonBean.class) == context.getBean(SingetonBean.class)));
System.out.println("prototype: " + (context.getBean(PrototypeBean.class) == context.getBean(PrototypeBean.class)));
System.out.println("default: " + (context.getBean(DefaultBean.class) == context.getBean(DefaultBean.class)));
// 输出 :
// singleton: true
// prototype: false
// default: true
}
}
class DefaultBean {
}
class SingetonBean {
}
class PrototypeBean {
}
//Spring-Scope.xml 文件放入resources文件夹中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="fun.zhaoxi.scope.SingetonBean" scope="singleton"/>
<bean class="fun.zhaoxi.scope.PrototypeBean" scope="prototype"/>
<bean class="fun.zhaoxi.scope.DefaultBean"/>
</beans>
基本作用域Bean的生命周期
从源码(版本 5.0.4)解读, Bean的生命周期的入口是getBean()方法, 大概分为以下的步骤:
- 当容器启动时, 会扫描所有的Bean信息, 并存储起来, 如果有Singleton的bean且没有设置延迟加载, 那么直接执行下面的初始化过程并缓存.
- 如果传入参数是类型为Class ,那么首先解析该Bean的名字, 默认BeanName = 类的全名; 如果传入名字是BeanName那么直接使用.
- 首先从步骤1的缓存中根据Key=BeanName读取Bean对象, 如果有直接返回.
- 如果没有的话, 就检测其父工厂是否包含该Bean, 如果有, 直接返回.
- 检测当前Bean是否有依赖Bean, 如果有依赖Bean, 首先构造依赖的Bean.
- 检测当前Bean的作用域, 如果是Singleton, 那么直接开始构造Bean; 如果是Prototype, 则现将当前BeanName写入到循环依赖检测的ThreadLocal
- 开始真正的创建Bean:
7-1: 构造Bean调用其构造函数(工厂方法)构造对象并设置其属性值(如果属性值, 构造函数参数是复杂对象, 先构造这些复杂参数)
7-2: 如果BeanClass实现了BeanNameAware, 那么执行其setBeanName()方法
7-3: 如果BeanClass实现了BeanClassLoaderAware, 那么执行其setBeanClassLoader()方法
7-4: 如果BeanClass实现了BeanFactoryAware, 那么执行其setBeanFactory()方法
7-5: 执行BeanPostProcessors的postProcessBeforeInitialization方法, 返回后置处理器包装后的Bean, 如果没有直接返回当前Bean
7-6: 执行bean的init-method方法
7-7: 执行BeanPostProcessors的postProcessAfterInitialization方法, 返回处理器包装后的Bean, 没有直接返回当前Bean
7-8: 真正返回Bean - 当容器关闭的时候, 执行Bean的destroy-method方法.
验证基本作用域生命周期
class DemoBean implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
private String name;
public DemoBean() {
System.out.println("ctor");
}
public void setName(String name) {
this.name = name;
System.out.println("set name " + name);
}
public void init() {
System.out.println("bean init");
}
public void destroy() {
System.out.println("bean destroy");
}
public void setBeanName(String name) {
System.out.println("set bean name " + name);
}
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("set bean ClassLoader ");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("set bean Factory ");
}
}
class DemoBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + " postProcessBeforeInitialization ");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + " postProcessAfterInitialization ");
return bean;
}
}
//Spring-Scope.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="demoBean" class="fun.zhaoxi.scope.DemoBean" init-method="init"
destroy-method="destroy" scope="prototype">
<property name="name" value="demoBean-name"/>
</bean>
<bean class="fun.zhaoxi.scope.DemoBeanPostProcessor"/>
</beans>
public class ScopeDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Scope.xml");
context.getBean("demoBean");
((ClassPathXmlApplicationContext) context).close();
}
}
// 输出:
// ctor
// set name demoBean-name
// set bean name demoBean
// set bean ClassLoader
// set bean Factory
// demoBean postProcessBeforeInitialization
// bean init
// demoBean postProcessAfterInitialization
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 zhao4xi@126.com
文章标题:Spring Bean的作用域和生命周期
文章字数:1.2k
本文作者:Zhaoxi
发布时间:2018-12-26, 15:09:21
最后更新:2019-09-21, 15:19:24
原始链接:http://zhao4xi.github.io/2018/12/26/Spring-Bean的作用域和生命周期/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。