單例範圍
如果使用 singleton 範圍定義 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 屬性時,將顯示訊息 changed property
,因為我們只檢索了相同的共享例項。
由於例項是在不同元件之間共享的,因此建議為無狀態物件定義單例範圍。
懶惰的單例豆
預設情況下,單例 bean 是預先例項化的。因此,將在建立 Spring 容器時建立共享物件例項。如果我們啟動應用程式,將顯示 “正在初始化單例 bean …” 訊息。
如果我們不希望預先例項化 bean,我們可以將 @Lazy 註釋新增到 bean 定義中。這將阻止在第一次請求 bean 之前建立 bean。
@Bean
@Lazy
public MyBean lazySingletonBean() {
return new MyBean("lazy singleton");
}
現在,如果我們啟動 Spring 容器,則不會出現 “正在初始化 lazy singleton bean …” 訊息。在第一次請求 bean 之前,不會建立 bean:
logger.info("Retrieving lazy singleton bean...");
context.getBean("lazySingletonBean");
如果我們執行應用程式同時定義了 singleton 和 lazy singleton bean,它將產生以下訊息:
Initializing singleton bean...
Retrieving lazy singleton bean...
Initializing lazy singleton bean...