spring 单例范围

示例

如果使用单例作用域定义了bean,则Spring容器中将仅初始化一个对象实例。对此bean的所有请求都将返回相同的共享实例。这是定义bean时的默认范围。

给定以下MyBean类:

public class MyBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
    private String property;

    public MyBean(String property) {
       this.property= property;
        LOGGER.info("Initializing {} bean...", property);
    }

    public String getProperty() {
        return this.property;
    }

    public void setProperty(String property) {
       this.property= property;
    }
}

我们可以使用@Bean批注定义一个单例bean:

@Configuration
public class SingletonConfiguration {

    @Bean
    public MyBean singletonBean() {
        return new MyBean("singleton");
    } 
}

以下示例从Spring上下文两次检索同一bean:

MyBean singletonBean1 = context.getBean("singletonBean", MyBean.class);
singletonBean1.setProperty("changed property");

MyBean singletonBean2 = context.getBean("singletonBean", MyBean.class);

记录singletonBean2属性时,将显示消息“已更改属性”,因为我们刚刚检索了相同的共享实例。

由于实例是在不同组件之间共享的,因此建议为无状态对象定义单例作用域。

懒惰的单例豆

默认情况下,单例bean是预先实例化的。因此,将在创建Spring容器时创建共享库实例。如果启动应用程序,将显示“正在初始化单例bean ...”消息。

如果我们不想预先实例化该bean,则可以将@Lazy批注添加到bean定义中。这将阻止在第一次请求之前创建该bean。

@Bean
@Lazy
public MyBean lazySingletonBean() {
    return new MyBean("lazy singleton");
}

现在,如果我们启动Spring容器,将不会出现“正在初始化惰性单例bean ...”消息。在第一次请求之前,不会创建该bean:

logger.info("检索懒惰的单例豆...");
context.getBean("lazySingletonBean");

如果我们同时定义了Singleton和Lazy Singleton Bean运行该应用程序,它将产生以下消息:

初始化单例bean ...
检索懒惰的单例豆...
初始化惰性单例豆...