Spring Bean的作用域和生命周期

Spring中5种作用域

在Spring配置Bean时, 可以通过设置scope属性来定义Bean的作用域, 按照scope的值来分, Bean的作用域分为以下几种:

  1. [基本作用域]singeton: 单例模式(默认方式), 每次返回同一个对象实例. 通过设置其 lazy-init参数可以设置是否延迟生成对象, 并将该对象存储在内部的ConcurrentHashMap中.
  2. [基本作用域]prototype: 原型模式, 每次都返回一个新的对象实例. 每次获取时才回去创建该对象.
  3. [Spring的Web作用域]request: 同一次请求返回同一个对象实例.
  4. [Spring的Web作用域]session: 同一次会话返回同一个对象实例.
  5. [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()方法, 大概分为以下的步骤:

  1. 当容器启动时, 会扫描所有的Bean信息, 并存储起来, 如果有Singleton的bean且没有设置延迟加载, 那么直接执行下面的初始化过程并缓存.
  2. 如果传入参数是类型为Class ,那么首先解析该Bean的名字, 默认BeanName = 类的全名; 如果传入名字是BeanName那么直接使用.
  3. 首先从步骤1的缓存中根据Key=BeanName读取Bean对象, 如果有直接返回.
  4. 如果没有的话, 就检测其父工厂是否包含该Bean, 如果有, 直接返回.
  5. 检测当前Bean是否有依赖Bean, 如果有依赖Bean, 首先构造依赖的Bean.
  6. 检测当前Bean的作用域, 如果是Singleton, 那么直接开始构造Bean; 如果是Prototype, 则现将当前BeanName写入到循环依赖检测的ThreadLocal中(构造完成后从ThreadLocal中移除), 再开始构造Bean.
  7. 开始真正的创建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
  8. 当容器关闭的时候, 执行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
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值