如果使用单例作用域定义了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 ... 检索懒惰的单例豆... 初始化惰性单例豆...