1.@Component注解與其衍生注解
(1) 在Spring中,@Component注解用于說明某個類是一個bean,之后Spring在類路徑掃描程序中會將該bean添加至容器中;@Component注解還有很多衍生注解,如@Repository, @Service和@Controller,它們分別用于三層架構中的持久層,業務層和控制層,因此,對于一個業務層的普通Service類,一般情況下用@Component或@Service都是可行的,但更推薦用@Service注解,因為該注解不僅能清晰的指明被標注的類是一個業務類,此外,這些注解還是Spring AOP的理想切入目標,能方便的對某一層進行切入(例如:切入控制層,進行權限校驗)
(2) Spring提供的許多注解都可以用作元注解,如Spring的@RestController注解,它就是將@Controller和@ResponseBody注解組合出來的一個新注解,使用該注解,在我們期望類中所有方法都回傳json格式資料時,就不用在每一個方法上都標注@ResponseBody注解了,因此,Spring推薦我們根據業務需要,結合元注解來實作自定義注解
2.自動掃描并注冊bean
(1) 上文我們提到了@Component注解等,那么,Spring該如何掃描到這些注解并將它們注入進容器中呢? 這就需要類路徑掃描注解@ComponentScan了,我們需要把它添加到有@Configuration注解標注的配置類上,在容器啟動后,Spring就會掃描指定包下的bean并將其注入進容器中,如下所示
//宣告3個類,這三個類均位于cn.example.spring.boke同一個包下,其中ExampleA和ExampleB被注解標注,表明它們是bean,需要被注入進容器中,ExampleC是一個普通的類
@Service
public class ExampleA { }
@Component
public class ExampleB { }
public class ExampleC { }
//使用@Configuration注解定義一個配置類,在該配置類上,使用@ComponentScan注解指定包掃描路徑為cn.example.spring.boke,這時,Spring就會掃描該包以及該包的子包下所有符合條件的bean,并將它們注入容器中,該注解等同于在之前提到過的<context:component-scan base-package="..."/>標簽
@Configuration
@ComponentScan("cn.example.spring.boke")
public class Config { }
//啟動容器,注意這里使用的是AnnotationConfigApplicationContext容器,而非之前的ClassPathXmlApplicationContext容器,而我們也不再需要xml組態檔,實作了完全的基于注解的配置
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
//列印結果如下,可以看到,容器掃描到了exampleA和exampleB以及我們的配置類config,而忽略了exampleC(其他的bean是Spring隱式自動添加的)
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
config
exampleA
exampleB
3.使用過濾器來自定義組件掃描規則
(1) 默認情況下,Spring僅檢測被@Component、@Repository、@Service、@Controller、@Configuration和以@Component等作為元注解的自定義注解(如:@RestController)標注的類,不過,我們可以通過自定義@ComponentScan注解中的過濾器屬性includeFilters和excludeFilters來修改這一默認行為,如下
//只修改上面例子中的配置類,此處假設我們只掃描被@Service注解標注的類,其自定義過濾規則如下
//includeFilters:要被注入的 excludeFilters:不要被注入的 @ComponentScan.Filter:指定過濾型別
@Configuration
@ComponentScan(basePackages = "cn.example.spring.boke",
includeFilters = @ComponentScan.Filter(Component.class),
excludeFilters = @ComponentScan.Filter(Service.class))
public class Config {
}
//輸出結果如下,可見我們的exampleA已被排除在外
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
config
exampleB
exampleC
過濾型別:
| 過濾型別 | 說明 |
|---|---|
| annotation(默認,按照注解過濾) | 如上面例子中的屬性excludeFilters = @ComponentScan.Filter(Service.class),就是排除掉所有被@Service注解標注的類 |
| assignable( 按照型別過濾) | 例如:excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = https://www.cnblogs.com/shame11/p/ExampleA.class),就是排除掉ExampleA這個型別的bean |
| aspectj(按照切面運算式過濾) | 例如:cn.example..*Service+,這是一個切入點運算式,會對所有符合這個切入點運算式的bean進行過濾 |
| regex(按照正則運算式過濾) | 同上,只不過滿足的是正則運算式 |
| custom(自定義過濾器) | 實作org.springframework.core.type.TypeFilter介面來自定義過濾器,實作自定義過濾規則 |
(2) 設定@ComponentScan注解中的useDefaultFilters屬性值為false,來禁用默認過濾器,即關閉Spring對于那些默認注解(如@Component等)的自動掃描檢測
4.定義組件的配置元資料
未完待續...
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543723.html
標籤:Java
