本文內容
- bean定義資訊的意義
- 介紹6種bean的作用域
bean定義資訊的意義
Spring中區分下類、類定義資訊,類實體物件的概念?不容易理解,以餐館中點炒飯為例,
類: 相當于你看到選單上炒飯這個菜品,有這個菜,
類定義資訊:相當于炒飯的烹飪法,烹飪法只有一份
類實體物件: 相當于按照上面烹飪法炒出來的一份炒飯,可以炒分多份出來,
Spring容器中創建了一個類定義資訊的,就可以根據這個定義資訊來創建個類實體物件出來,這個理解了很關鍵,Spring中不僅可以控制 bean 物件中的各種依賴項和配置值,還可以控制 bean 額作用范圍,
介紹6種bean的作用域
Spring Framework 支持6個bean的作用域,其中4個僅在web型別的 ApplicationContext 中可用,詳細見下表
| 作用域 | 描述 |
|---|---|
| singleton | (默認)將單個 bean 定義限定為每個 Spring IoC 容器的單個物件實體, |
| prototype | 將單個 bean 定義限定為任意數量的物件實體 |
| request | 將單個 bean 定義限定為單個 HTTP 請求的生命周期,也就是說,每個 HTTP 請求都有自己的 bean 實體,該實體是在單個 bean 定義的后面創建的,僅在web型別的 ApplicationContext有效, |
| session | 將單個 bean 定義限定為 HTTP 會話的生命周期,僅在web型別的 ApplicationContext有效, |
| application | 將單個 bean 定義限定為 ServletContext 的生命周期,僅在web型別的 ApplicationContext有效, |
| websocket | 將單個 bean 定義限定為 WebSocket 的生命周期,僅在web型別的 ApplicationContext有效, |
從 Spring 3.0 開始,執行緒范圍可用,但默認情況下未注冊,
SimpleThreadScope感興趣可以詳細看下面自定義作用域,
singleton
只有一個單例 bean 的共享實體被管理,并且所有對具有與該 bean 定義匹配的一個或多個 ID 的 bean 的請求都會導致 Spring 容器回傳一個特定的 bean 實體,"蝎子粑粑獨一份",注意是一個IoC容器內,

prototype
原型作用域下每次容器都會創建一個新的 bean 實體,通常來說,對有狀態 bean適合使用原型,對無狀態 bean適合使用單例,
下面的配置節指定了bean的作用域是原型的,
<bean id="accountService" scope="prototype"/>
與其他范圍相比,Spring 不管理原型 bean 的完整生命周期,容器實體化、配置和以其他方式組裝原型物件并將其傳遞給客戶端,由客戶端去管理,bean生命周期后面介紹,
request, session, application, webSocket
這4個在web的應用背景關系中使用的作用域,暫不展開講,留給后面寫spring mvc 專門講,
自定義作用域和使用
如何自定義?
可以通過實作org.springframework.beans.factory.config.Scope自定義作用域,Scope 介面有四種方法可以從作用域中獲取物件,將它們從作用域中移除,并讓它們被銷毀,
package org.springframework.beans.factory.config;
public interface Scope {
// 從底層范圍回傳具有給定名稱的物件
Object get(String name, ObjectFactory<?> objectFactory);
// 從底層范圍中洗掉具有給定的物件
Object remove(String name);
// 注冊要在作用域中指定物件的銷毀時執行的回呼
void registerDestructionCallback(String name, Runnable callback);
// 省略
}
打鐵要趁熱,直接上SimpleThreadScope的原始碼,決議下執行緒級別作用域是如何實作的,
package org.springframework.context.support;
public class SimpleThreadScope implements Scope {
private static final Log logger = LogFactory.getLog(SimpleThreadScope.class);
// 1 bean是存放在ThreadLocal中的 系結了當前執行緒
private final ThreadLocal<Map<String, Object>> threadScope =
new NamedThreadLocal<Map<String, Object>>("SimpleThreadScope") {
@Override
protected Map<String, Object> initialValue() {
return new HashMap<>();
}
};
// 2 查ThreadLocal,有對應bean就直接回傳,沒有就創建一個放入ThreadLocal,在回傳
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> scope = this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
scope.put(name, scopedObject);
}
return scopedObject;
}
// 3 從ThreadLocal中移除bean
@Override
@Nullable
public Object remove(String name) {
Map<String, Object> scope = this.threadScope.get();
return scope.remove(name);
}
// 4 銷毀回呼
@Override
public void registerDestructionCallback(String name, Runnable callback) {
logger.warn("SimpleThreadScope does not support destruction callbacks. " +
"Consider using RequestScope in a web environment.");
}
@Override
@Nullable
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return Thread.currentThread().getName();
}
}
如何使用?
-
先將自定義的scope注入到容器中
編碼的方式注冊:
ConfigurableBeanFactory介面提供了registerScope來注冊自定義的scope,Scope threadScope = new SimpleThreadScope(); beanFactory.registerScope("thread", threadScope);組態檔方式的注冊: 使用
CustomScopeConfigurer以宣告方式進行注冊<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean > <property name="scopes"> <map> <entry key="thread"> <bean /> </entry> </map> </property> </bean> </beans> -
bean配置中使用
使用方式普通的scope一樣,
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean > <property name="scopes"> <map> <entry key="thread"> <bean /> </entry> </map> </property> </bean> <bean id="thing2" scope="thread"> <property name="name" value="https://www.cnblogs.com/kongbubihai/p/Rick"/> <aop:scoped-proxy/> </bean> <bean id="thing1" > <property name="thing2" ref="thing2"/> </bean> </beans>
總結
本文Spring中的7種作用域,以及如何自定義作用域并使用,下一篇介紹基于注解的Spring容器配置,
知識分享,轉載請注明出處,學無先后,達者為先!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/423183.html
標籤:Java
