[Spring實戰系列](14)Bean的自動檢測
即使
有助於完全消除Spring注解中的和元素,但是還是不能完全消除,仍然需要使用元素顯示定義Bean。因此元素出現了,它除了完成一樣的工作,還允許Spring自動檢測Bean和定義Bean。這就意味著我們不使用元素,Spring應用中的大多數(或者所有)Bean都能夠實現定義和裝配。
為了配置Spring自動檢測,需要使用
元素來代替元素:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
元素會掃描指定的包以及所有子包,並查找出能夠自動注冊為Spring Bean的類。base-package屬性標示了元素所掃描的包。
為自動檢測標注Bean
默認情況下,查找使用構造型(stereotype)注解所標注的類,這些特殊的注解如下:
類型 |
說明 |
@component
通用的構造型注解,標示該類為Spring 組件。
@Controller
標識將該類定義為Spring MVC controller。
@Repository
標識將該類定義為數據倉庫(例如:Dao層)。
@Service
標識將該類定義為服務(例如:Service層)。
1. @component
假設我們應用上下文中僅僅包含Student和School兩個Bean。我們可以配置元素並使用@Component注解標注Student和School類,從而消除顯示的定義。
package com.sjf.bean;
import org.springframework.stereotype.Component;
/**
* 學校實體類
* @author sjf0115
*
*/
@Component
public class School {
private String name;
private String location;
...
}
Spring掃描com.sjf.bean包時,會發現使用Component注解所標注的School,並自動將它注冊為Spring Bean。Bean的ID默認為無限定類名(第一個字母小寫),School Bean的ID為school。
下面我們標注Student類:
package com.sjf.bean;
import org.springframework.stereotype.Component;
/**
* 學生實體類
* @author sjf0115
*
*/
@Component("studentBean")
public class Student {
private String name;
private int age;
private School school;
...
}
這種場景下,我們指定了一個Bean ID作為@Component注解的參數。該Bean 的ID不會使用默認的類名,而是顯示的命名為studentBean。
當使用時,基於注解的自動檢測只是一種掃描策略。下面讓我們來了解其他的掃描策略來查找候選Bean。
2. 過濾組件掃描
在如何掃描來獲得候選Bean方面,元素非常靈活。通過為配置和子元素,我們可以隨意調整掃描行為。
假設我們基於注解讓自動注冊所有實現某個接口的類,我們不得不浏覽每一個接口實現的類,並使用@Component來標注它們,非常不方便。所以我們替換掉基於注解的組件掃描策略,再增加一個包含過濾器來要求注冊以及排除類。
的type和expression屬性一起協作來定義組件掃描策略。我們還可以選擇如下任意一種過濾器:
類型 |
說明 |
annotation
過濾器掃描使用指定注解標注的那些類,通過expression屬性指定要掃描的注解
assignable
過濾器掃描派生於expression屬性所指定類型的那些類。
aspectj
過濾器掃描與expression屬性所指定的AspectJ表達式所匹配的那些類。
custom
使用自定義的org.springframework.core.type.TypeFilter實現類,該類由expression屬性指定。
regex
過濾器掃描類的名稱與expression屬性所指定的正則表達式所匹配的那些類。
除了使用告知哪些類需要注冊為Spring Bean以外,我們還可以使用來告知哪些類不需要注冊為Spring Bean。
我們實現了兩個接口,一個是Worker接口(員工),一個是Performer(表演者)。然後根據這兩個接口,分別實現了接口的實現類:
package com.sjf.bean;
/**
* 農民實體類
* @author sjf0115
*
*/
public class Farmer implements Worker {
public void work() {
System.out.println("正在辛勤的耕地...");
}
}
我們使用告知實現了Worker接口的實現類需要注冊為Spring Bean,使用來告知實現了Perfomer接口的實現類不需要注冊為Spring Bean。
我們測試一下上述過濾器是否起作用了:
Farmer farmer = (Farmer) context.getBean("farmer");
farmer.work();
運行結果:
正在辛勤的耕地...
Singer singer = (Singer) context.getBean("singer");
singer.perform();
運行結果:
Exceptioninthread"main"org.springframework.beans.factory.NoSuchBeanDefinitionException:Nobeannamed'singer'isdefined
參考:《Spring實戰》