在使用xml方式配置時,我們只需要在xml中配置如下代碼:
<context:component-scan base-package="包名"></context:component-scan>
那么在java代碼中使用如下四個注解,並且這些注解所在的包名是上面配置的包及其子包,那么spring會幫我們把相應的bean加如到IOC容器中。
- @Controller
- @Service
- @Repository
- @Component
在注解的方式下如何實現呢?在我們的配置類的上面加上如下注解即可
@ComponentScan(value={"包名1","包名2"})
此時該注解指定的幾個包名及其子包中如果有類被上面四個注解修飾,那么就會自動被注入到IOC容器中。
注意:如果ComponentScan沒有其它配置的化,默認掃描與其配置類相同的包。
1、實戰
新建一個maven工程,添加如下依賴
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
1、BookController
package com.yefengyu.annotation.controller; import org.springframework.stereotype.Controller; @Controller public class BookController { }
2、BookService
package com.yefengyu.annotation.service; import org.springframework.stereotype.Service; @Service public class BookService { }
3、BookRepository
package com.yefengyu.annotation.repository; import org.springframework.stereotype.Repository; @Repository public class BookRepository { }
4、主配置類
package com.yefengyu.annotation.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(value = "com.yefengyu.annotation") public class MainConfig { }
5、測試
public static void main(String[] args) { ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } }
6、結果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookRepository
bookService
結果打印出如上內容,說明上面三個注解的bean都被添加到容器中。
2、規則過濾
@ComponentScan除了value 屬性之外,還有其他屬性,其中比較常用的是如下兩個:
- excludeFilters :排除哪些規則
- includeFilters :指定哪些規則
他們的作用就是指定過濾規則。
1、指定規則
對於上面的代碼,只需要修改主配置類中ComponentScan注解中的內容即可:
@ComponentScan(value = "com.yefengyu.annotation", includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Service.class)},useDefaultFilters = false)
上面的注解的含義是在com.yefengyu.annotation及其子包下面,將注解為Service的bean加入到容器中。注意useDefaultFilters 默認為true,表示使用默認的過濾規則:不過濾;如果需要指定規則,那么就需要將useDefaultFilters 設置為false。注意includeFilters 和useDefaultFilters 同時使用即可。
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookService
2、排除規則
對於上面的代碼,只需要修改主配置類中ComponentScan注解中的內容即可:
@ComponentScan(value = "com.yefengyu.annotation", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Service.class)})
如果要排除某些規則,就要使用excludeFilters ,注意不需要使用useDefaultFilters ,默認即可。
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController bookRepository
上面注解的含義就是在com.yefengyu.annotation及其子包下面,將注解為Controller的bean排除容器之外。
3、FilterType的類型
- ANNOTATION:注解,常用
- ASSIGNABLE_TYPE:給定類型,該類型及其子類、接口的實現類都起作用
- ASPECTJ
- REGEX:正則
- CUSTOM:自定義
自定義類型的使用方式:
package com.yefengyu.annotation; 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; import java.io.IOException; public class MyTypeFilter 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(); if (className.contains("er")) { return true; } return false; } }
實現TypeFilter接口,重寫match方法,滿足條件的則返回true.
然后指定掃描策略:
@ComponentScan(value = "com.yefengyu.annotation", excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class)})
結果如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookRepository
將類中含有er的排除在外。
4、指定多個ComponentScan
1、在jdk8以后可以直接寫多個ComponentScan
@ComponentScan(basePackages = "com.yefengyu.annotation1")
@ComponentScan(basePackages = "com.yefengyu.annotation2")
2、也可以使用ComponentScans注解
@ComponentScans(value = { @ComponentScan(basePackages = "com.yefengyu.annotation1"), @ComponentScan(basePackages = "com.yefengyu.annotation2") })