Spring中Bean的作用域详解

  • Bean简介
  • Bean作用域
  • Singleton介绍
  • Prototype介绍
  • Request介绍
  • Session介绍


Bean简介

在Spring中,组成应用程序的主体、由SpringIoC容器所管理的对象,被称之为bean。简单来讲,也就是由IoC容器进行初始化、装配、管理(生命周期和依赖关系)的对象。

Bean作用域

abstract类里面spring的bean为空 spring bean存在哪_User

其中request、session的作用域仅在基于web的SpringContext环境中使用。

Singleton介绍

Spring缺省作用域,Singleton是单例类型,默认在创建容器时就自动创建了一个bean的对象,这样不管是否使用,都已经存在,并且每次获取到的是同一对象
当一个bean的作用域为Singleton,那么SpringIoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

XML中将一个bean定义为Singleton:

<bean id="user" class="com.ahy.pojo.User" scope="singleton">
</bean>

测试:

@Test
    void test01() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicaitonContext.xml");
        User user1 =(User) context.getBean("user");
        User user2 =(User) context.getBean("user");
        System.out.println(user1 == user2);//true
    }

配置类中声明bean为Singleton:

@Configuration
public class SpringConfiguration {
    @Bean
    @Scope("singleton")
    public People people(){
        return new People("jack",55);
    }

    public class People{
        private String name;
        private int age;

    public People(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
}

测试:

@Test
    public void test01(){
        AnnotationConfigApplicationContext context
 		= new AnnotationConfigApplicationContext(SpringConfiguration.class);
        User.People people1 =(User.People) context.getBean("people");
        User.People people2 =(User.People) context.getBean("people");
        System.out.println(people1 == people2 );//true
    }

设置bean为懒加载,也就是在调用容器的getBean()方法时再加载:

<bean id="people" class="com.ahy.pojo.User.People"
lazy-init="true"></bean>

Prototype介绍

Prototype是原型类型,在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,并且我们每次获取到的对象都不是同一个对象
当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求时(将其注入到另一个bean中,或者调用容器的getBean()方法),都会创建一个新的bean实例。

根据经验,对有状态的bean应该使用Prototype作用域,而对无状态的bean应该使用Singleton作用域

XML中将bean定义为Prototype:

<bean id="people" class="com.ahy.pojo.User.People" scope="prototype"></bean>

或者:

<bean id="people" class="com.ahy.pojo.User.People"  singleton="false"></bean>

测试:

@Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        User user1 =(User) context.getBean("user");
        User user2 =(User) context.getBean("user");
        System.out.println(user1 == user2);//false
    }

配置类中声明bean为Prototype:

@Configuration
public class SpringConfiguration {
    @Bean
    @Scope("prototype")
    public People people(){
        return new People("jack",55);
    }
    
    public class People{
        private String name;
        private int age;
        
    public People(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
}

测试:

@Test
    public void test01(){
       // ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        AnnotationConfigApplicationContext context
     	= new AnnotationConfigApplicationContext(User.class);
        User.People user1 =(User.People) context.getBean("people");
        User.People user2 =(User.People) context.getBean("people");
        System.out.println(user1 == user2);//false
    }

Request介绍

当一个bean作用域为Request,表示在一次HTTP请求中,一个bean对应一个实例;即每个HTTP请求都会有各自的bean实例。该作用域仅在基于web的SpringApplicaitonContext情形下有效。

XML中将bean定义为Request:

<bean id="loginAction" class="com.ahy.LoginAction" scope="request"></bean>

针对每次HTTP请求。Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该实例仅在当前HTTP request请求内有效,因此可以根据需要放心的更改该实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁

Session介绍

当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
XML中将bean定义为Session:

<bean id="userPreferences" class="com.ahy.UserPreferences" scope="session"/>

针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉