Spring學習(二)

@ComponentScan向Spring IOC容器中注入組件

在使用Spring框架開發應用的過程當中,你們都知道使用Spring開發應用程序,咱們應用程序中大多數的Bean都是經過Spring的IOC容器來管理。將Bean注入到Spring IOC容器中的方式多種多樣,如經過傳統的XML方式注入,經過註解的方式注入等。本文咱們就來詳細的探索一下在使用註解配置的方式注入Bean時,@ComponentScan註解組件掃描的應用。正則表達式

1、@ComponentScan介紹

顧名思義,@ComponentScan註解提供給咱們的功能就是自動組件掃描,將指定包下的被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean自動掃描注入到Spring IOC容器中,由Spring IOC容器統一管理這些Bean。
註解中的屬性項:spring

  • basePackages與value: 用於指定包的路徑,進行自動掃描;
  • basePackageClasses: 用於指定某個類的包的路徑進行掃描;
  • nameGenerator: bean的名稱的生成器;
  • useDefaultFilters: 是否開啓對@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解的Bean進行自動掃描注入;
  • includeFilters: 包含的過濾條件,包括:
  • FilterType.ANNOTATION:按照註解的方式過濾;
  • FilterType.ASSIGNABLE_TYPE:按照給定類型的方式過濾;
  • FilterType.ASPECTJ:使用ASPECTJ表達式的方式過濾;
  • FilterType.REGEX:使用正則表達式的方式過濾;
  • FilterType.CUSTOM:自定義規則過濾;
  • excludeFilters: 排除的過濾條件,用法和includeFilters同樣;

2、使用@ComponentScan註解的方式注入組件

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

在com.training.componentscan包下咱們分別建立component、controller、repository、service、config、filter包。app

在component包中建立SoftWareComponent類,加@Component註解:框架

@Component
public class SoftWareComponent {
        //... ...
}

在controller包中建立SoftWareController類,加@Controller註解:單元測試

@Controller
public class SoftWareController {
    //... ...
}

在repository包中建立SoftWareRepository類,加@Repository註解:測試

@Repository
public class SoftWareRepository {
       //... ...
}

在service包中建立SoftWareService類,加@Service註解:spa

@Service
public class SoftWareService {
        //... ...
}

在config包中建立ComponentScanConfig類,寫入以下內容:.net

@Configuration //告訴Spring這是一個配置類
@ComponentScan(basePackages = "com.training.componentscan")
//掃描com.training.componentscan包及其子包中被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean
public class ComponentScanConfig {
       //... ...
}

咱們建立一個單元測試類IOCTest,用來測試看有哪些組件被注入到了Spring IOC容器中。code

public class IOCTest {
    @Test
    public void test() {
        AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(ComponentScanConfig.class);
        
        String[] names = application.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

執行單元測試咱們獲得以下結果:component

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
componentScanConfig
softWareComponent
softWareController
softWareRepository
softWareService

從執行結果咱們能夠看到,容器啓動後,咱們全部加了@Repository、@Service、@Controller、@Component、@Configuration註解的Bean都被注入到了Spring IOC容器中。

3、excludeFilters應用舉例

在上面的例子中,在使用組件掃描時,若是咱們想過濾某些Bean,不但願全部加了@Repository、@Service、@Controller、@RestController、@Component、@Configuration這些註解的Bean都被注入到Spring IOC中,咱們該怎麼處理呢?

@ComponentScan註解有一個excludeFilters屬性,經過給該屬性設置對應的值能夠過濾掉指定條件的Bean自動注入到Spring IOC容器中,可過濾的類型咱們在上文中已經說明,這裏再也不贅述。

3.1 FilterType.ANNOTATION(註解的方式過濾)

使用註解方式過濾指定註解的Bean很簡單,咱們修改配置類ComponentScanConfig以下,過濾掉@Controller註解的Bean自動注入Spring IOC容器中。

@Configuration //告訴Spring這是一個配置類
@ComponentScan(basePackages = "com.training.componentscan",excludeFilters={
        @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})
//掃描com.training.componentscan包及其子包中被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean
public class ComponentScanConfig {
    
}

執行單元測試咱們能夠獲得以下結果:

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
componentScanConfig
softWareComponent
softWareRepository
softWareService

從執行結果咱們能夠看到,容器啓動後,被@Controller註解的Bean被過濾掉了。

3.2 FilterType.ASSIGNABLE_TYPE(給定類型的方式過濾)

使用給定類型的方式過濾,即過濾指定的Bean,咱們修改配置類ComponentScanConfig以下,過濾掉SoftWareRepository這個Bean。

@Configuration //告訴Spring這是一個配置類
@ComponentScan(basePackages = "com.training.componentscan",excludeFilters={
        @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
        @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={SoftWareRepository.class})
})
//掃描com.training.componentscan包及其子包中被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean
public class ComponentScanConfig {
    
}

執行單元測試咱們能夠獲得以下結果:

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
componentScanConfig
softWareComponent
softWareService

從執行結果咱們能夠看到,容器啓動後,SoftWareRepository這個Bean被過濾掉了。

3.3 FilterType.ASPECTJ(ASPECTJ表達式的方式過濾)

使用ASPECTJ表達式的方式過濾Bean,首先咱們須要加入切面aspectj的依賴。

<dependency>
<groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.2</version>
</dependency>

咱們使用ASPECTJ表達式的方式過濾掉以Component結尾的Bean,修改ComponentScanConfig以下:

@Configuration //告訴Spring這是一個配置類
@ComponentScan(basePackages = "com.training.componentscan",excludeFilters={
        @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
        @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={SoftWareRepository.class}),
        @Filter(type=FilterType.ASPECTJ,pattern={"com.training.componentscan..*Component"})
})
//掃描com.training.componentscan包及其子包中被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean
public class ComponentScanConfig {
    
}

執行單元測試,咱們獲得以下結果:

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
componentScanConfig
softWareService

從執行結果咱們能夠看到,容器啓動後,以Component結尾的SoftWareComponent這個Bean被過濾掉了。

3.4 FilterType.REGEX(正則表達式的方式過濾)

咱們使用正則表達式的方式過濾掉以Service結尾的Bean,修改ComponentScanConfig以下:

@Configuration //告訴Spring這是一個配置類
@ComponentScan(basePackages = "com.training.componentscan",excludeFilters={
        @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
        @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={SoftWareRepository.class}),
        @Filter(type=FilterType.ASPECTJ,pattern={"com.training.componentscan..*Component"}),
        @Filter(type=FilterType.REGEX,pattern=".*Service")
})
//掃描com.training.componentscan包及其子包中被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean
public class ComponentScanConfig {
    
}

執行單元測試,獲得以下結果:

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
componentScanConfig

從執行結果咱們能夠看到,容器啓動後,以Service結尾的SoftWareService這個Bean被過濾掉了。

3.5 FilterType.CUSTOM(自定義規則過濾)

咱們使用自定義過濾器過濾類名中不含有"Co"的Bean。

自定義過濾器要實現org.springframework.core.type.filter.TypeFilter接口,定義本身的過濾器ComponentFilter實現TypeFilter接口以下:

public class ComponentFilter implements TypeFilter {
    /**
     * metadataReader:讀取到的當前正在掃描的類的信息 metadataReaderFactory:能夠獲取到其餘任何類信息
     */
    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);
        if(!className.contains("Co")){
            return true;
        }
        
        return false;
    }
}

修改ComponentScanConfig以下:

@Configuration //告訴Spring這是一個配置類
@ComponentScan(basePackages = "com.training.componentscan",excludeFilters={
        @Filter(type=FilterType.CUSTOM,classes={ComponentFilter.class})
})
//掃描com.training.componentscan包及其子包中被@Repository、@Service、@Controller、@RestController、@Component、@Configuration註解所標註的Bean
public class ComponentScanConfig {
    
}

執行單元測試咱們獲得以下結果:

---->>>>>com.training.componentscan.IOCTest
---->>>>>com.training.componentscan.IOCTest1
---->>>>>com.training.componentscan.component.SoftWareComponent
---->>>>>com.training.componentscan.controller.SoftWareController
---->>>>>com.training.componentscan.filter.ComponentFilter
---->>>>>com.training.componentscan.repository.SoftWareRepository
---->>>>>com.training.componentscan.service.SoftWareService
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
componentScanConfig
softWareComponent
softWareController

從執行結果可知,全部沒有包含「Co」的Bean已經被所有過濾,只有類名包含"Co"的Bean注入到了Spring IOC容器中。

只包含includeFilters屬性的使用與excludeFilters屬性的使用基本一致,這裏再也不贅述。

小結:

本文咱們經過註解的方式講述了@ComponentScan的應用,以及經過實例演示的方式向你們展現了自動掃描注入時如何經過不一樣方式排除、包含知足指定條件的Bean,但願你們共勉。

轉載:https://blog.csdn.net/zyhlwzy/article/details/89180214

相關文章
相關標籤/搜索