Spring框架之Bean Scope
Spring框架支持六個作用域,其中四個只有在使用web感知的ApplicationContext時才可用。
Spring支持以下6中bean scopes:
- singleton:單例模式(默認(rèn)值),在Spring容器中只會創(chuàng)建一個實(shí)例。
- prototype:原型模式,每次通過Spring容器獲取bean時,容器都會新建一個實(shí)例。
- request:每次HTTP請求都會創(chuàng)建一個實(shí)例,但只在http request范圍有效。
- session:?在http session生命周期內(nèi),共享一個實(shí)例,不同session有不同的實(shí)例。
- application:在ServletContext生命周期內(nèi),只有一個實(shí)例。
- webSocket:在webSocket范圍內(nèi)只有一個實(shí)例。
Singleton scope
Spring容器默認(rèn)的作用域,只有一個共享的單例bean實(shí)例被管理,id與bean定義的id匹配的bean請求,spring容器都會返回一個特定的bean實(shí)例。換句話說,當(dāng)您定義一個bean為單例時,Spring IoC容器只會創(chuàng)建該bean的一個實(shí)例。這個實(shí)例存儲在緩存中,所有后續(xù)對這個bean的請求和引用都返回緩存對象。
基于java configuration方式定義一個singleton的bean
public class AppConfiguration {
("singleton") // default scope
public UserService userService(){
return new UserService();
}
}
prototype scope
原型模式會導(dǎo)致每次請求都會創(chuàng)新一個新的bean實(shí)例,就是說當(dāng)一個bean被注入到另一個bean中,或者通過getBean()方法調(diào)用請求它時會新創(chuàng)建一個bean實(shí)例。通常,有狀態(tài)的bean使用prototype scope,無狀態(tài)的bean使用singleton scope。與其它scope不同,spring容器不管理原型scope的整個生命周期,容器實(shí)例化、配置和以其他方式組裝原型對象,都將其交給client,而無需進(jìn)一步記錄該原型實(shí)例。
基于java configuration方式定義一個prototype的bean
public class AppConfiguration {
("prototype")
public UserService userService(){
return new UserService();
}
}
具有原型bean依賴項(xiàng)的單例bean
當(dāng)您將單例bean與原型bean的依賴項(xiàng)一起使用時,請注意,依賴項(xiàng)是在實(shí)例化時解析的。因此,如果依賴項(xiàng)將原型注入到單例bean中,則會實(shí)例化一個新的原型bean,然后將依賴項(xiàng)注入到單例bean中。原型實(shí)例是唯一一個提供給單例bean的實(shí)例。
Request、Session、Application和WebSocket作用域
Request、Session、Application、WebSocket作用域僅在使用web感知的Spring ApplicationContext實(shí)現(xiàn)(如XmlWebApplicationContext)時可用。如果將這些作用域與常規(guī)Spring IoC容器(如ClassPathXmlApplicationContext)一起使用,則會拋出一個IllegalStateException,未知bean作用域。
鑒于目前技術(shù)發(fā)展采用前后端分離模式開發(fā),已很少單獨(dú)使用Spring web mvc模式,此處不在講述這四個作用域,大家可以參考官方文檔了解。
InitializingBean和DisposableBean
在Spring中,為了與容器bean的生命周期管理進(jìn)行交互,可以實(shí)現(xiàn)InitializingBean和DisposableBean接口。容器初始化時執(zhí)行AfterPropertieSet(),銷毀是調(diào)用destroy(),以便bean在初始化和銷毀bean時執(zhí)行某些操作。
@PostConstruct和@PreDestroy注釋通常被認(rèn)為是新版Spring應(yīng)用程序中接收生命周期回調(diào)的最佳實(shí)踐。使用這些注釋意味著您的bean沒有耦合到特定于Spring的接口。
- 實(shí)現(xiàn)InitializingBean接口,在所有bean設(shè)置完properties后將運(yùn)行afterPropertiesSet()。
- 實(shí)現(xiàn)DisposableBean接口,在Spring容器釋放bean后運(yùn)行destroy()。
InitializingBean和DisposableBean示例
在本例中,我們將使用afterPropertiesSet()方法在應(yīng)用程序啟動期間使用用戶對象填充內(nèi)存中的列表數(shù)據(jù)結(jié)構(gòu)。我們還將在應(yīng)用程序關(guān)閉期間使用destroy()方法從列表中刪除用戶對象。
package com.demo.spring;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
public class DatabaseInitiaizer implements InitializingBean, DisposableBean {
private List < User > listOfUsers = new ArrayList < > ();
public void afterPropertiesSet() throws Exception {
User user = new User(1, "User");
User user1 = new User(2, "Admin");
User user2 = new User(3, "SuperAdmin");
listOfUsers.add(user);
listOfUsers.add(user1);
listOfUsers.add(user2);
System.out.println("-----------List of users added in init() method ------------");
for (Iterator < User > iterator = listOfUsers.iterator(); iterator.hasNext();) {
User user3 = (User) iterator.next();
System.out.println(user3.toString());
}
// save to database
}
public void destroy() {
// Delete from database
listOfUsers.clear();
System.out.println("-----------After of users removed from List in destroy() method ------------");
for (Iterator < User > iterator = listOfUsers.iterator(); iterator.hasNext();) {
User user3 = (User) iterator.next();
System.out.println(user3.toString());
}
System.out.println("List is clean up ..");
}
}
package com.demo.spring;
public class User {
private Integer id;
private String name;
public User() {}
public User(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
package com.demo.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
(basePackages = "com.demo.spring")
public class AppConfig {
}
注意:@ComponentScan注解掃描指定包中所有包中包含@Component注解的類,basePackages指定包路徑。
package com.demo.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.close();
}
}
Output:
-----------List of users added in init() method ------------
User [id=1, name=User]
User [id=2, name=Admin]
User [id=3, name=SuperAdmin]
-----------After of users removed from List in destroy() method -------
List is clean up ..