javascript
Spring深入理解之ComponentScan___@ComponentScan 详解
Spring深入理解之ComponentScan
一、概述
ComponentScan顧名思義包掃描,底層其實就可以通過遞歸算法+反射將其裝載成bean來實現的,實在開發過程中,Spring已經幫我們實現好了,我們其實就可以直接使用XML或者注解的形式來進行業務處理。
二、@ComponentScan的作用
@ComponentScan注解有兩個作用
作用一:掃描含有@Component,@Controller,@Service和@Repository的類,并將其注入到spring容器中。
作用二:掃描含有@Configuration的類,并使其生效。
分析:作用一相信大家都明白其含義,再次不在贅述。作用二舉例說明,例如Config2可以掃描到config2_test目錄,該目錄下不僅含有@Component,@Controller,@Service和@Repository注解標注的四個類,還包含Config1配置類。Config1配置類,可以掃描到config1_test目錄,并且里面還包含一個@Bean注解。
三、同一個配置類上多個@ComponentScan可能會報錯
下面的配置類在我公司電腦的idea版本里是可以將config3_test目錄下的所有類都注冊到spring容器中,但是在我家里的電腦上以及另一個同事的電腦上會報編譯期錯誤,代碼運行也會出錯。
四、@ComponentScans的使用
由于同一個類上直接寫多個@ComponentScan可能會報錯,因此建議使用@ComponentScans,它可以解決直接在一個配置類上寫多個@ComponentScan在有些電腦或idea版本上報錯的問題。
@ComponentScan 詳解
@ComponentScan 的作用就是根據定義的掃描路徑,把符合掃描規則的類裝配到spring容器中,注解定義如下。
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;String resourcePattern() default "**/*.class";boolean useDefaultFilters() default true;ComponentScan.Filter[] includeFilters() default {};ComponentScan.Filter[] excludeFilters() default {};boolean lazyInit() default false;@Retention(RetentionPolicy.RUNTIME)@Target({})public @interface Filter {FilterType type() default FilterType.ANNOTATION;@AliasFor("classes")Class<?>[] value() default {};@AliasFor("value")Class<?>[] classes() default {};String[] pattern() default {};} }basePackages與value: 用于指定包的路徑,進行掃描
basePackageClasses: 用于指定某個類的包的路徑進行掃描
nameGenerator: bean的名稱的生成器
useDefaultFilters: 是否開啟對@Component,@Repository,@Service,@Controller的類進行檢測
includeFilters: 包含的過濾條件
- FilterType.ANNOTATION:按照注解過濾
 - FilterType.ASSIGNABLE_TYPE:按照給定的類型
 - FilterType.ASPECTJ:使用ASPECTJ表達式
 - FilterType.REGEX:正則
 - FilterType.CUSTOM:自定義規則
 
excludeFilters: 排除的過濾條件,用法和includeFilters一樣
我的工程結構如下,測試對controller和service的掃描,其中HelloController沒有加@Controller等任何注解,就是一個普通類。
 
修改配置類如下:應用默認的過濾器,掃描service包:
@Configuration @ComponentScan(value = "com.xhx.spring.service",useDefaultFilters = true ) public class MyConfig { }系統注入了兩個service進去
 
改成如下所示:HelloController所在的包的類也被掃描了進去
@Configuration @ComponentScan(value = "com.xhx.spring.service",useDefaultFilters = true,basePackageClasses = HelloController.class ) public class MyConfig { }系統中會注入下面就給類
把默認的過濾器關掉,掃描帶Controller注解的。
@Configuration @ComponentScan(value = "com.xhx.spring",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})} ) public class MyConfig { }按照類的類型掃描,雖然HelloController沒有加注解,但是被注入到了spring容器中
@Configuration @ComponentScan(value = "com.xhx.spring",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {HelloController.class})} ) public class MyConfig { }自定義掃描過濾器
package com.xhx.spring.componentscan.config;import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter;import java.io.IOException;public class MyTypeFilter implements TypeFilter {@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {String className = metadataReader.getClassMetadata().getClassName();if(className.contains("Controller")){return true;}return false;} }修改配置類
@Configuration @ComponentScan(value = "com.xhx.spring",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})} ) public class MyConfig { }輸出結果:
 
輸出spring容器中的bean的測試類:只過濾輸出了名字中含有hello的類。
package com.xhx.spring.componentscan;import com.xhx.spring.componentscan.config.MyConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.test.context.junit4.SpringRunner;import java.util.Arrays; import java.util.List; import java.util.stream.Collectors;@RunWith(SpringRunner.class) @SpringBootTest public class ComponentScanApplicationTests {@Testpublic void testLoads() {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);List<String> hello = Arrays.stream(context.getBeanDefinitionNames()).collect(Collectors.toList());hello.stream().filter(name->name.contains("hello")).peek(System.out::println).count();}}總結
以上是生活随笔為你收集整理的Spring深入理解之ComponentScan___@ComponentScan 详解的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: SQLIntegrityConstrai
 - 下一篇: 小米手机上安装https证书(例如pem