Bootstrap

Bean作用域

1 作用域

简单理解:Bean作用域即对象创建的数量。

序号作用域描述
1singleton默认作用域。每次依赖注入或者查找都只有一份Bean对象
2prototype原型作用域。每次依赖注入或者查找都会新建Bean对象
3session每个Http Session都会新建一个Bean对象,Bean存在于HttpSession,适用于WebApplicationContext
4request每个Http请求的都会新生成一个Bean对象,Bean存在于ServletRequest,适用于WebApplicationContext
5websocket每个WebSocket生命周期新建一个Bean对象,适用于WebApplicationContext

1.1 singleton

任何时刻,某个容器内都只有一个Bean对象。示意如图1.1所示。
在这里插入图片描述

图1.1 singleton作用域

1.2 prototype

每次依赖注入或者查找都会新建Bean对象。示意如图1.2所示。

在这里插入图片描述

图1.2 prototype作用域

2 测试

2.1 实体

去除方法:toString(),以便打印时输出对象地址,通过对象地址判断是否为同一个对象。

package com.monkey.tutorial.modules.user.vo;

import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;

/**
 * 用户基础信息.
 *
 * @author xindaqi
 * @since 2021-06-05 08:42:41
 */
@Document(collection = "baseUserVO")
public class BaseUserVO implements Serializable {

    private static final long serialVersionUID = 4774966681660887538L;
    /**
     * 用户主键id,MySQL自动生成
     */
    @Field("id")
    private long id;

    /**
     * 用户id
     */
    @Field("userId")
    private String userId;

    /**
     * 用户姓名
     */
    @Field("username")
    private String username;

    /**
     * 用户性别
     */
    @Field("sex")
    private String sex;

    public BaseUserVO() {

    }

    public BaseUserVO(String userId, String username, String sex) {
        this.userId = userId;
        this.username = username;
        this.sex = sex;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getSex() {
        return sex;
    }

    /**
     * 自定义初始化Bean的初始化方法.
     */
    public void init() {
        System.out.println(">>>>>>>>>>BaseUserVO自定义初始化方法init(),START");
        System.out.println(">>>>>>>>>>BaseUserVO自定义初始化方法init()执行");
        System.out.println(">>>>>>>>>>BaseUserVO自定义初始化方法init(),END");
    }

//    @Override
//    public String toString() {
//        return "BaseUserInformation{" +
//                "id=" + id +
//                ", userId='" + userId + '\'' +
//                ", username='" + username + '\'' +
//                ", sex='" + sex + '\'' +
//                '}';
//    }
}

2.2 查找bean

使用@Scope新建两种Bean:Singleton和Prototype,
每次通过getBean查询Bean。

package com.monkey.tutorial.common.mybean;

import com.monkey.tutorial.modules.user.vo.BaseUserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

/**
 * Bean作用域(Scope)样例.
 *
 * @author xindaqi
 * @date 2022-01-27 17:44
 */
public class ScopeTest {

    @Bean(name = "singleton")
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public BaseUserVO userSingleton() {
        return new BaseUserVO("0x001", "singleton", "female");
    }

    @Bean(name = "prototype")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public BaseUserVO userPrototype() {
        return new BaseUserVO("0x002", "prototype", "female");
    }

    public static void main(String[] args) {

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScopeTest.class);

        BaseUserVO baseUserVOSingleton1 = (BaseUserVO) applicationContext.getBean("singleton");
        BaseUserVO baseUserVOSingleton2 = (BaseUserVO) applicationContext.getBean("singleton");
        BaseUserVO baseUserVOSingleton3 = (BaseUserVO) applicationContext.getBean("singleton");
        System.out.format(">>>>>>>Singleton bean %n 1:%s, %n 2:%s, %n 3:%s %n", baseUserVOSingleton1, baseUserVOSingleton2, baseUserVOSingleton3);

        BaseUserVO baseUserVOPrototype1 = (BaseUserVO) applicationContext.getBean("prototype");
        BaseUserVO baseUserVOPrototype2 = (BaseUserVO) applicationContext.getBean("prototype");
        BaseUserVO baseUserVOPrototype3 = (BaseUserVO) applicationContext.getBean("prototype");
        System.out.format(">>>>>>>Prototype bean %n 1:%s, %n 2:%s, %n 3:%s", baseUserVOPrototype1, baseUserVOPrototype2, baseUserVOPrototype3);

    }
}

2.3 结果

运行结果如图2.1所示。
由图2.1可知,Singleton作用域每次查找Bean都只有一个对象;
Prototype作用域每次查询都会新建一个对象。
在这里插入图片描述

3 小结

  • singleton |默认作用域。每次依赖注入或者查找都只有一份Bean对象
  • prototype |原型作用域。每次依赖注入或者查找都会新建Bean对象
  • session |每个Http Session都会新建一个Bean对象,Bean存在于HttpSession,适用于WebApplicationContext
  • request |每个Http请求的都会新生成一个Bean对象,Bean存在于ServletRequest,适用于WebApplicationContext
  • websocket |每个WebSocket生命周期新建一个Bean对象,适用于WebApplicationContext

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;