Bean的作用域和初始化时机(singleton&prototype)

在Spring中Bean的作用域是可以自己定义的,如果你想每次需要bean时都产生一个新的bean实例时你可以声明Bean的作用域的属性值为prototype。

而在Spring中Bean的作用域属性默认为singleton,其实也就是单例的。

Spring 框架支持以下五个作用域,

作用域描述
singleton

在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean() 
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

本次就只讨论前两个作用域,当你使用web-aware ApplicationContext 的时候,剩余的三个也是可以使用的。

singleton作用域就是默认的作用域,当你创建Spring IOC的容器是时候,Bean对象无论是否使用,它也会随着Spring Ioc容器一起创建出来。

当你每次需要获取一个Bean对象的时候,获取的其实都是一个Bean对象。

创建一个简单的实体类,在无参构造方法里打印一句话

package com.yjc.beanlife;

public class Student {
    private Integer age;
    private String name;

    public Student() {
        System.out.println("初始化时执行无参构造!");
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在applicationContext.xml把Student声明到Spring 容器当中,设置bean节点的值为singleton(当然也可以不设置,因为默认值就是singleton)

<?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="student" class="com.yjc.beanlife.Student" scope="singleton"/>
</beans>

执行测试方法,在测试方法里加载配置文件,创建Spring容器

package com.yjc.beanlife;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/yjc/beanlife/applicationContext.xml");

    }
}

测试结果

 由上图可见,当bean节点的scope属性的值为singleton时,无论你是否使用这个Bean对象,bean初始化的时机是和Spring容器同时创建的。就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。

接下来把bean节点的scope属性值更改为prototype,修改测试方法

package com.yjc.beanlife;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/yjc/beanlife/applicationContext.xml");
        Student student = applicationContext.getBean("student", Student.class);
        Student student1 = applicationContext.getBean("student", Student.class);
        System.out.println(student);
        System.out.println(student1);
    }
}

测试结果如下

 当bean节点的scope属性值为prototype时,bean的初始化时机就变为了,当你去获取Bean对象的时候,Spring容器才会创建一个对象,而且每一次创建的都是不同的对象。

根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

原文地址:https://www.cnblogs.com/yjc1605961523/p/11752071.html