javascript
Spring5参考指南:组件扫描
文章目錄
- 組件掃描
- @Component
- 元注解和組合注解
- 組件內(nèi)部定義Bean元數(shù)據(jù)
- 為自動檢測組件命名
- 為自動檢測的組件提供作用域
- 生成候選組件的索引
組件掃描
上一篇文章我們講到了annotation-config配置,它主要用于bean內(nèi)部的屬性注入。而bean本身則需要通過配置的方式來定義。如果想使用配置的方式來定義bean,則可以使用component-scan,如下:
<context:component-scan base-package="com.flydean"/>component-scan會掃描類路徑里面的注解注解,包括(@Component, @Repository, @Service,
@Controller, @RestController, @ControllerAdvice, 和@Configuration ), 當(dāng)然component-scan默認(rèn)包含了annotation-config,我們可以直接在這些配置bean中使用上篇文章講到的注解。
@Component
@Component表示該bean是一個組件,@Component是任何Spring管理的組件的通用原型。@Repository、@Service和@Controller是@Component針對更具體的用例(分別在持久性、服務(wù)和表示層中)的特殊注解。因此,您可以用@Component注解組件類,但是,通過用@Repository、@Service或@Controller注解它們,您的類更具有語義性。通常更適合在AOP中做進一步的業(yè)務(wù)邏輯處理。
元注解和組合注解
所謂元注解就是可以用在其他注解中的注解。 像之前提到的@Component就是@Service的元注解。如下:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service {// .... }@Component會導(dǎo)致@Service和@Component一樣被對待。
當(dāng)然你也可以組合使用元注解,或者自定義元注解。例如,Spring的@SessionScope注解將作用域名稱硬編碼為session,但仍允許自定義proxyMode。以下列表顯示了sessionScope注解的定義:
你可以不定義@SessionScope里面的proxyMode, 如下:
@Service @SessionScope public class SessionScopedService {// ... }你也可以重寫proxyMode,如下:
@Service @SessionScope(proxyMode = ScopedProxyMode.INTERFACES) public class SessionScopedUserService implements UserService {// ... }#@ComponentScan和filters
上面我們講到,要是要使用組件掃描,需要在XML配置context:component-scan, 其實也可以使用注解的形式,如下所示:
@Configuration @ComponentScan(basePackages = "com.flydean.beans") public class AppConfig {}@ComponentScan可以配置一些filters用來過濾不需要的組件。如下所示:
@Configuration @ComponentScan(basePackages = "com.flydean.beans",includeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),excludeFilters = @ComponentScan.Filter(BeanA.class)) public class BeanAConfig { }下表是支持的filter類型和例子:
| annotation(默認(rèn)) | org.example.SomeAnnotation | type基本的目標(biāo)組件 |
| assignable | org.example.SomeClass | 目標(biāo)組件可分配給(擴展或?qū)崿F(xiàn))的類(或接口)。 |
| aspectj | org.example…*Service+ | 匹配目標(biāo)組件的AspectJ類型 |
| regex | org\.example\.Default.* | 匹配目標(biāo)主鍵內(nèi)名的正則表達式 |
| custom | org.example.MyTypeFilter | org.springframework.core.type .TypeFilter的自定義實現(xiàn) |
組件內(nèi)部定義Bean元數(shù)據(jù)
Spring組件還可以為容器提供bean定義元數(shù)據(jù)。您可以使用用于在@Configuration annotated類中定義bean元數(shù)據(jù)的相同@Bean注解來實現(xiàn)這一點。以下示例顯示了如何執(zhí)行此操作:
@Component public class FactoryMethodComponent {@Bean@Qualifier("public")public BeanA publicInstance() {return new BeanA();}public void doWork() {// Component method implementation omitted} }InjectionPoint
從SpringFramework4.3開始,還可以聲明InjectionPoint類型的工廠方法參數(shù),來創(chuàng)建Bean。
注意,這只適用于bean實例的實際創(chuàng)建,而不適用于現(xiàn)有實例的注入。因此,這個特性對于原型范圍的bean最有意義。
@Component public class InjectPointFactoryMethodComponent {@Bean@Scope("prototype")public BeanA prototypeInstance(InjectionPoint injectionPoint) {return new BeanA("prototypeInstance for " + injectionPoint.getMember());} }常規(guī)Spring組件中的@Bean方法的處理方式與Spring@Configuration類中的對應(yīng)方法不同。不同的是,@Component類沒有用cglib來增強以截獲方法和字段的調(diào)用。cglib代理是調(diào)用@Configuration classes中通過@Bean methods內(nèi)的方法或字段創(chuàng)建對協(xié)作對象的bean元數(shù)據(jù)引用的方法。
你可以將@Bean方法聲明為靜態(tài)方法,允許在不將其包含的配置類創(chuàng)建為實例的情況下調(diào)用它們。在定義post-processor bean(例如,BeanFactoryPostProcessor或BeanPostProcessor類型)時,這是特別有意義的,因為這樣的bean在容器生命周期的早期就被初始化,應(yīng)該避免在此時觸發(fā)配置的其他部分。
由于技術(shù)限制,對static @Bean方法的調(diào)用永遠(yuǎn)不會被容器截獲,即使是在@Configuration類(如本節(jié)前面所述)中也是如此:cglib子類只能重寫非靜態(tài)方法。因此,直接調(diào)用另一個@Bean方法相當(dāng)于標(biāo)準(zhǔn)Java的new方法,導(dǎo)致從工廠方法本身直接返回一個獨立的實例。
要注意: @Configuration類中的常規(guī)@Bean方法必須是可重寫的,也就是說,它們不能聲明為私有或最終的。
為自動檢測組件命名
默認(rèn)情況下,可以提供value屬性給@Component、@Repository、@Service和@Controller),從而為Bean命名。
如果這樣的注解不包含value,則默認(rèn)bean名稱生成器將返回小寫的非限定類名。例如,如果檢測到以下組件類,則名稱為myMovieLister和movieFinderImpl:
@Service("myMovieLister") public class SimpleMovieLister {// ... } @Repository public class MovieFinderImpl implements MovieFinder {// ... }如果您不想依賴默認(rèn)的bean命名策略,可以提供一個自定義的bean命名策略。首先,實現(xiàn)BeanNameGenerator接口,并確保包含一個默認(rèn)的無參數(shù)構(gòu)造函數(shù)。然后,在配置掃描器時提供完全限定的類名,如下面的示例注解和bean定義所示:
public class MyNameGenerator implements BeanNameGenerator {@Overridepublic String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {return null;} } @Configuration @ComponentScan(basePackages = "com.flydean", nameGenerator = MyNameGenerator.class) public class BeanNameConfig { }為自動檢測的組件提供作用域
與一般的Spring管理組件一樣,自動檢測組件的默認(rèn)和最常見的作用域是singleton。但是,有時您需要一個可以由@Scope注解指定的不同范圍。可以在注解中提供作用域的名稱,如下示例所示:
@Scope("prototype") @Component("beanA") public class BeanA {public BeanA(){}public BeanA(String name){} }自定義范圍解析
要為范圍解析提供自定義策略,而不是依賴基于注解的方法,可以實現(xiàn)ScopeMetadataResolver接口。如下所示:
public class MyScopeResolver implements ScopeMetadataResolver {@Overridepublic ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {return null;} } @Configuration @ComponentScan(basePackages = "com.flydean", scopeResolver = MyScopeResolver.class) public class BeanScopeResolverConfig { }scoped-proxy
當(dāng)使用某些非單例作用域時,可能需要為作用域?qū)ο笊纱怼榇?#xff0c;組件掃描元素上可以有一個scoped-proxy 屬性。三個可能的值是:no、interfaces和targetClass。例如,以下配置將生成標(biāo)準(zhǔn)JDK動態(tài)代理:
@Configuration @ComponentScan(basePackages = "com.flydean", scopedProxy = ScopedProxyMode.INTERFACES) public class ScopedProxyConfig { }生成候選組件的索引
雖然類路徑掃描速度非常快,但是可以通過在編譯時創(chuàng)建一個靜態(tài)候選列表來提高大型應(yīng)用程序的啟動性能。
要生成索引,需要每個模塊添加一個附加依賴項,該模塊包含作為組件掃描指令目標(biāo)的組件。下面的示例說明如何使用Maven:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context-indexer</artifactId><version>5.1.8.RELEASE</version><optional>true</optional></dependency> </dependencies>這個過程生成一個包含在JAR文件中的META-INF/spring.components文件。
當(dāng)在類路徑上找到META-INF/Spring.components時,索引將自動啟用。如果某個索引部分可用于某些庫(或用例),但無法為整個應(yīng)用程序生成,則可以通過將spring.index.ignore設(shè)置為true(作為系統(tǒng)屬性或類路徑根目錄下的spring.properties文件)來回滾到常規(guī)類路徑安排(就像根本沒有索引一樣)。
本節(jié)的例子可以參考 component-scan.
更多精彩內(nèi)容且看:
- 區(qū)塊鏈從入門到放棄系列教程-涵蓋密碼學(xué),超級賬本,以太坊,Libra,比特幣等持續(xù)更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續(xù)更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續(xù)更新
- java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程
更多教程請參考flydean的博客
總結(jié)
以上是生活随笔為你收集整理的Spring5参考指南:组件扫描的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring5参考指南:基于注解的容器配
- 下一篇: gradle idea java ssm