詳解Spring系列之@ComponentScan自動掃描組件
無注解方式component-scan使用
之前,我們需要掃描工程下一些類上所標注的注解,這些常用注解有:
@Controller,@Service,@Component,@Repository
通過在Spring的配置文件中配置<context:component-scan>掃描對應包下掃描這些注解的方式:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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-2.5.xsd">
<!--@Controller,@Service,@Component,@Repository-->
<context:component-scan base-package="com.jektong.spring"/>
</beans>注解方式@ComponentScan使用
建三個類,依次將
@Controller,@Repository,@Service,標注這些類:

圖1
現(xiàn)在通過使用注解@ComponentScan的方式來掃描所在包下面的這些類:之前定義的PersonConfig修改:
package com.jektong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.jektong.spring.Person;
@Configuration
@ComponentScan("com.jektong")
public class PersonConfig {
@Bean("person01")
public Person person() {
return new Person("李四",21);
}
}測試,看是否掃描到這些注解所標注的類:PersonTest.java
@Test
public void test02() {
ApplicationContext ac = new AnnotationConfigApplicationContext(PersonConfig.class);
Person bean = ac.getBean(Person.class);
System.out.println(bean);
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String string : beanDefinitionNames) {
System.out.println(string);
}
}測試效果:除了Spring要自動加載的配置類以外也顯示了剛才添加的配置類:

圖2
為何會出現(xiàn)PersonConfig,因為@Configuration本 身就是@Component注解的:

圖3
@ComponentScan的掃描規(guī)則
如果需要指定配置類的掃描規(guī)則,@ComponentScan提供對應的掃描方式@Filter進行配置類的過濾:
// 掃描包的時候只規(guī)定掃描一些注解配置類。
Filter[] includeFilters() default {};
// 掃描包的時候可以排除一些注解配置類。
Filter[] excludeFilters() default {};Filter其實也是一個注解,相當于@ComponentScan的子注解,可以看圖4:

圖4
Filter對應的過濾規(guī)則如下:
第一種:掃描包的時候只規(guī)定掃描一些注解配置類【includeFilters】。
使用這個includeFilters過濾規(guī)則,必須解除默認的過濾規(guī)則,
使用【useDefaultFilters = false】:
package com.jektong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import com.jektong.spring.Person;
@Configuration
@ComponentScan(value = "com.jektong",includeFilters = {
@Filter(type = FilterType.ANNOTATION,value= {Controller.class})
},useDefaultFilters = false )
public class PersonConfig {
@Bean("person01")
public Person person() {
return new Person("李四",21);
}
}這樣就只會掃描用@Controller,標注的配置類交給Spring容器中了:

圖5
第二種:掃描包的時候可以排除一些注解配置類【excludeFilters】。

圖6
@Filter看上圖,有5種不同類型的過濾策略。拿第一種舉例,我們需要過濾使用@Controller注解的配置類:
package com.jektong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import com.jektong.spring.Person;
@Configuration
@ComponentScan(value = "com.jektong",excludeFilters = {
@Filter(type = FilterType.ANNOTATION,value= {Controller.class})
} )
public class PersonConfig {
@Bean("person01")
public Person person() {
return new Person("李四",21);
}
}測試看一下發(fā)現(xiàn)圖2中的personController不會交給Spring容器去管理了:

圖7
上面的圖6展示出5種不同類型的過濾策略,上面介紹了注解類型(FilterType.ANNOTATION),還有四種:
重點看一下CUSTOM自定義掃描策略。

從源碼看,自定義掃描注解類型需要實現(xiàn)TypeFilter接口,下面就寫一個實現(xiàn)類MyFilter.java:在實現(xiàn)類中可以自定義配置規(guī)則:
package com.jektong.config;
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
public class MyFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// 查看當前類的注解。
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 查看當前掃描類的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 獲取當前類資源
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("className===>" + className);
// 只要類名包含er則注冊Spring容器
if(className.contains("er")) {
return true;
}
return false;
}
}測試:
PersonConfig 中進行掃描:
package com.jektong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import com.jektong.service.PersonService;
import com.jektong.spring.Person;
@Configuration
@ComponentScan(value = "com.jektong",includeFilters = {
@Filter(type = FilterType.CUSTOM,value= {MyFilter.class})
},useDefaultFilters = false )
public class PersonConfig {
@Bean("person01")
public Person person() {
return new Person("李四",21);
}
}可以看出掃描出包下面的類只要帶“er”的全部掃描出來,并配置給Spring容器:

ASSIGNABLE_TYPE:按照指定的類型去加載對應配置類:
package com.jektong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import com.jektong.service.PersonService;
import com.jektong.spring.Person;
@Configuration
@ComponentScan(value = "com.jektong",includeFilters = {
@Filter(type = FilterType.ASSIGNABLE_TYPE,value= {PersonService.class})
},useDefaultFilters = false )
public class PersonConfig {
@Bean("person01")
public Person person() {
return new Person("李四",21);
}
}盡管我們將PersonService.java上的注解去掉,使用ASSIGNABLE_TYPE依然會加載出來(自行測試)。
ASPECTJ與REGEX基本不用,不用了解。
以上就是@ComponentScan的具體用法,該興趣的話可以看一下源碼。
到此這篇關于詳解Spring系列之@ComponentScan自動掃描組件的文章就介紹到這了,更多相關Spring @ComponentScan內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java開發(fā)者就業(yè)需要掌握的9大專業(yè)技能
這篇文章主要為大家詳細介紹了java就業(yè)前需要掌握的專業(yè)技能,感興趣的小伙伴們可以參考一下2016-09-09
springboot+mybatis+redis 二級緩存問題實例詳解
Mybatis默認沒有開啟二級緩存,需要在全局配置(mybatis-config.xml)中開啟二級緩存。本文講述的是使用Redis作為緩存,與springboot、mybatis進行集成的方法。需要的朋友參考下吧2017-12-12
java實現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問題示例
這篇文章主要介紹了java實現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問題示例,需要的朋友可以參考下2014-05-05
SpringBoot中的RestTemplate使用方法詳解
這篇文章主要介紹了SpringBoot中的RestTemplate使用方法詳解,為了方便使用,這里我封裝成一個工具類來靜態(tài)調(diào)用RestTemplate,基于SpringBoot2.4.2版本,需要的朋友可以參考下2024-01-01

