javascript
Spring之Bean的配置(二)
目錄
一、Bean的配置
1.自動裝配
(1)簡介
(2)缺點
2.繼承Bean
3.依賴Bean配置
4.Bean的作用域
5.使用外部屬性文件
6.注冊PropertyPlaceholderConfigurer
7.通過工廠方法配置Bean
(1)靜態工廠
(2)實例工廠
8.通過FactoryBean配置Bean
9.基于注解配置Bean
10.組件裝配
11.泛型依賴注入
二、spEL表達式
1.字面量
2.引用Bean、屬性和方法
3.運算符
三、IOC中 Bean 的生命周期方法
1.創建Bean后置處理器
2.添加后置處理器后 Bean 的生命周期
一、Bean的配置
1.自動裝配
(1)簡介
-
Spring IOC 容器可以自動裝配 Bean. 需要做的僅僅是在 <bean> 的 autowire 屬性里指定自動裝配的模式
-
byType(根據類型自動裝配): 若 IOC 容器中有多個與目標 Bean 類型一致的 Bean. 在這種情況下, Spring 將無法判定哪個 Bean 最合適該屬性, 所以不能執行自動裝配
-
byName(根據名稱自動裝配): 必須將目標 Bean 的名稱和屬性名設置的完全相同
-
constructor(通過構造器自動裝配): 當 Bean 中存在多個構造器時, 此種自動裝配方式將會很復雜. 不推薦使用
(2)缺點
-
在 Bean 配置文件里設置 autowire 屬性進行自動裝配將會裝配 Bean 的所有屬性. 然而, 若只希望裝配個別屬性時, autowire 屬性就不夠靈活了
-
autowire 屬性要么根據類型自動裝配, 要么根據名稱自動裝配, 不能兩者兼而有之
-
一般情況下,在實際的項目中很少使用自動裝配功能,因為和自動裝配功能所帶來的好處比起來,明確清晰的配置文檔更有說服力一些
2.繼承Bean
Spring 允許繼承 bean 的配置, 被繼承的 bean 稱為父 bean. 繼承這個父 Bean 的 Bean 稱為子 Bean
子 Bean 從父 Bean 中繼承配置, 包括 Bean 的屬性配置
子 Bean 也可以覆蓋從父 Bean 繼承過來的配置
父 Bean 可以作為配置模板, 也可以作為 Bean 實例. 若只想把父 Bean 作為模板, 可以設置 <bean> 的abstract 屬性為 true, 這樣 Spring 將不會實例化這個 Bean
并不是 <bean> 元素里的所有屬性都會被繼承. 比如: autowire, abstract 等
也可以忽略父 Bean 的 class 屬性, 讓子 Bean 指定自己的類, 而共享相同的屬性配置. 但此時 abstract 必須設為 true
3.依賴Bean配置
-
Spring 允許用戶通過 depends-on 屬性設定
-
Bean 前置依賴的Bean會在本 Bean 實例化之前創建好
-
如果前置依賴于多個 Bean,則可以通過逗號,空格或的方式配置 Bean 的名稱
4.Bean的作用域
-
在 Spring 中, 可以在 <bean> 元素的 scope 屬性里設置 Bean 的作用域
-
默認情況下, Spring 只為每個在 IOC 容器里聲明的 Bean 創建唯一一個實例, 整個 IOC 容器范圍內都能共享該實例:所有后續的 getBean() 調用和 Bean 引用都將返回這個唯一的 Bean 實例.該作用域被稱為 singleton, 它是所有 Bean 的默認作用域
5.使用外部屬性文件
-
在配置文件里配置 Bean 時, 有時需要在 Bean 的配置里混入系統部署的細節信息(例如: 文件路徑, 數據源配置信息等). 而這些部署細節實際上需要和 Bean 配置相分離
-
Spring 提供了一個 PropertyPlaceholderConfigurer 的 BeanFactory 后置處理器, 這個處理器允許用戶將 Bean 配置的部分內容外移到屬性文件中. 可以在 Bean 配置文件里使用形式為 ${var} 的變量, PropertyPlaceholderConfigurer 從屬性文件里加載屬性, 并使用這些屬性來替換變量
-
Spring 還允許在屬性文件中使用 ${propName},以實現屬性之間的相互引用
6.注冊PropertyPlaceholderConfigurer
-
Spring 2.5 之后: 可通過 context:property-placeholder 元素簡化:
-
<beans> 中添加 context Schema 定義
-
在配置文件中加入如下配置(以下為C3P0連接池配置的示范)
7.通過工廠方法配置Bean
(1)靜態工廠
/*靜態工廠方法:直接調用類的靜態方法返回Bean的實例*/ public class StaticStuFactory { ?private static Map<String, Student> stus = new HashMap<>(); ?static {stus.put("001", new Student("jack", 18));stus.put("002", new Student("rose", 20));} ?public static Student getStus(String id) {return stus.get(id);} } <!--通過靜態工廠方法來配置Bean,注意不是配置靜態工廠方法實例,而是配置bean實例 --> <!--class:指向靜態方法的全類名factory-method:指向靜態工廠方法的名字constructor-arg:如果工廠方法需要傳入參數,則必須使用此標簽配置參數--> <bean id="stu" class="com.itheima.spring.beans.StaticStuFactory" factory-method="getStus"><constructor-arg value="001"></constructor-arg> </bean>(2)實例工廠
public class InstanceStuFactory {private Map<String, Student> stus = null; ?public InstanceStuFactory() {stus=new HashMap<>();stus.put("001", new Student("tom", 15));stus.put("002", new Student("marry", 16));} ?public Student getStudent(String id) {return stus.get(id);} } <!-- 配置工廠的實例--> <bean id="stuFactory" class="com.itheima.spring.beans.InstanceStuFactory"></bean> ? <!-- 通過實例工廠來配置bean --> <bean id="stu2" factory-bean="stuFactory" factory-method="getStudent" ><constructor-arg value="001"></constructor-arg> </bean>8.通過FactoryBean配置Bean
public class StuFactoryBean implements FactoryBean<Student> {private String name;private int age; ?public void setName(String name) {this.name = name;} ?public void setAge(int age) {this.age = age;} ?@Overridepublic Student getObject() throws Exception {return new Student(name, age);} ?@Overridepublic Class<?> getObjectType() {return Student.class;} ?@Overridepublic boolean isSingleton() {return true;} } <!--通過FactoryBean來配置Bean的實例class:指向FactoryBean的全類名property:配置FactoryBean的屬性 --> <bean id="stu3" class="com.itheima.spring.beans.StuFactoryBean"><property name="name" value="allen"></property><property name="age" value="25"></property> </bean>9.基于注解配置Bean
-
組件掃描(component scanning): Spring 能夠從 classpath 下自動掃描, 偵測和實例化具有特定注解的組件
-
特定組件包括:
-
@Component: 基本注解, 標識了一個受 Spring 管理的組件
-
@Respository: 標識持久層組件
-
@Service: 標識服務層(業務層)組件
-
@Controller: 標識表現層組件
-
-
對于掃描到的組件, Spring 有默認的命名策略: 使用非限定類名, 第一個字母小寫. 也可以在注解中通過 value 屬性值標識組件的名稱
-
當在組件類上使用了特定的注解之后, 還需要在 Spring 的配置文件中聲明 <context:component-scan>
-
base-package 屬性指定一個需要掃描的基類包,Spring 容器將會掃描這個基類包里及其子包中的所有類
-
當需要掃描多個包時, 可以使用逗號分隔
-
如果僅希望掃描特定的類而非基包下的所有類,可使用 resource-pattern 屬性過濾特定的類
-
context:include-filter 子節點表示要包含的目標類
-
context:exclude-filter 子節點表示要排除在外的目標類
-
context:component-scan 下可以擁有若干個 context:include-filter 和 context:exclude-filter 子節點
-
-
context:include-filter 和 context:exclude-filter 子節點支持多種類型的過濾表達式
10.組件裝配
-
context:component-scan 元素還會自動注冊 AutowiredAnnotationBeanPostProcessor 實例, 該實例可以自動裝配具有 @Autowired 和 @Resource 、@Inject注解的屬性
-
@Autowired 注解自動裝配具有兼容類型的單個 Bean屬性
-
構造器, 普通字段(即使是非 public), 一切具有參數的方法都可以應用@Autowired 注解
-
默認情況下, 所有使用 @Autowired 注解的屬性都需要被設置. 當 Spring 找不到匹配的 Bean 裝配屬性時, 會拋出異常, 若某一屬性允許不被設置, 可以設置 @Autowired 注解的 required 屬性為 false
-
默認情況下, 當 IOC 容器里存在多個類型兼容的 Bean 時, 通過類型的自動裝配將無法工作. 此時可以在 @Qualifier 注解里提供 Bean 的名稱. Spring 允許對方法的入參標注 @Qualifiter 已指定注入 Bean 的名稱
-
@Autowired 注解也可以應用在數組類型的屬性上, 此時 Spring 將會把所有匹配的 Bean 進行自動裝配
-
@Autowired 注解也可以應用在集合屬性上, 此時 Spring 讀取該集合的類型信息, 然后自動裝配所有與之兼容的 Bean
-
@Autowired 注解用在 java.util.Map 上時, 若該 Map 的鍵值為 String, 那么 Spring 將自動裝配與之 Map 值類型兼容的 Bean, 此時 Bean 的名稱作為鍵值
-
-
Spring 還支持 @Resource 和 @Inject 注解,這兩個注解和 @Autowired 注解的功用類似
-
@Resource 注解要求提供一個 Bean 名稱的屬性,若該屬性為空,則自動采用標注處的變量或方法名作為 Bean 的名稱
-
@Inject 和 @Autowired 注解一樣也是按類型匹配注入的 Bean, 但沒有 reqired 屬性
-
建議使用 @Autowired 注解
11.泛型依賴注入
-
Spring 4.x 中可以為子類注入子類對應的泛型類型的成員變量的引用
-
Spring 允許通過 <import> 將多個配置文件引入到一個文件中,進行配置文件的集成。這樣在啟動 Spring 容器時,僅需要指定這個合并好的配置文件就可以
-
import 元素的 resource 屬性支持 Spring 的標準的路徑資源
二、spEL表達式
-
Spring 表達式語言(簡稱SpEL):是一個支持運行時查詢和操作對象圖的強大的表達式語言
-
語法類似于 EL:SpEL 使用 #{…} 作為定界符,所有在大框號中的字符都將被認為是 SpEL
-
SpEL 為 bean 的屬性進行動態賦值提供了便利
-
通過 SpEL 可以實現:
-
通過 bean 的 id 對 bean 進行引用
-
調用方法以及引用對象中的屬性
-
計算表達式的值
-
正則表達式的匹配
-
1.字面量
-
整數:
-
小數:
-
科學計數法:
-
Boolean:
2.引用Bean、屬性和方法
(1)引用其它對象
<property name="enabled" value="#{對象}"/>(2)引用其它對象的屬性
<property name="enabled" value="#{對象.指定屬性值}"/>(3)調用其它對象的方法,支持鏈式操作
<property name="enabled" value="#{對象.方法名()}"/>(4)調用靜態方法或靜態屬性
? 通過 T() 調用一個類的靜態方法,它將返回一個 Class Object,然后再調用相應的方法或屬性
<property name="initValue" value="#{T(java.lang.Math).PI}"/>3.運算符
-
算術運算符:+, -, *, /, %, ^
-
比較運算符: <, >, ==, <=, >=, lt, gt, eq, le, ge
-
邏輯運算符號: and, or, not, |
-
if-else 運算符:?: (ternary): (Elvis)
-
正則表達式:matches
三、IOC中 Bean 的生命周期方法
-
Spring IOC 容器可以管理 Bean 的生命周期, Spring 允許在 Bean 生命周期的特定點執行定制的任務
-
Spring IOC 容器對 Bean 的生命周期進行管理的過程:
-
通過構造器或工廠方法創建 Bean 實例
-
為 Bean 的屬性設置值和對其他 Bean 的引用
-
調用 Bean 的初始化方法
-
Bean 可以使用了
-
當容器關閉時, 調用 Bean 的銷毀方法
-
-
在 Bean 的聲明里設置 init-method 和 destroy-method 屬性, 為 Bean 指定初始化和銷毀方法
1.創建Bean后置處理器
-
Bean 后置處理器允許在調用初始化方法前后對 Bean 進行額外的處理.
-
Bean 后置處理器對 IOC 容器里的所有 Bean 實例逐一處理, 而非單一實例. 其典型應用是: 檢查 Bean 屬性的正確性或根據特定的標準更改 Bean 的屬性
-
對Bean 后置處理器而言, 需要實現BeanPostProcessor接口. 在初始化方法被調用前后, Spring 將把每個 Bean 實例分別傳遞給上述接口的以下兩個方法:
- Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
- Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
2.添加后置處理器后 Bean 的生命周期
-
通過構造器或工廠方法創建 Bean 實例
-
為 Bean 的屬性設置值和對其他 Bean 的引用
-
將 Bean 實例傳遞給 Bean 后置處理器的 postProcessBeforeInitialization 方法
-
調用 Bean 的初始化方法
-
將 Bean 實例傳遞給 Bean 后置處理器的 postProcessAfterInitialization方法
-
Bean 可以使用了
-
當容器關閉時, 調用 Bean 的銷毀方法
總結
以上是生活随笔為你收集整理的Spring之Bean的配置(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring之Bean的配置(一)
- 下一篇: HTTP Status 405 - JS