企业网站定制开发Spring注解详解:@ComponentScan自动扫描组件使用

目录


企业网站定制开发无注解方式-scan使用

之前,企业网站定制开发我们需要扫描工程下一企业网站定制开发些类上所标注的注解,企业网站定制开发这些常用注解有:

@Controller,@Service,@Component,@Repository

通过在Spring企业网站定制开发的配置文件中配置<context:component-scan>扫描对应包下扫描这些注解的方式:

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:p="http://www.springframework.org/schema/p"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context-2.5.xsd">
  9. <!--@Controller,@Service,@Component,@Repository-->
  10. <context:component-scan base-package="com.jektong.spring"/>
  11. </beans>

注解方式@ComponentScan使用

建三个类,依次将

@Controller@Repository@Service,标注这些类:

图1

现在通过使用注解@ComponentScan的方式来扫描所在包下面的这些类:之前定义的PersonConfig修改:

  1. package com.jektong.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.Configuration;
  5. import com.jektong.spring.Person;
  6. @Configuration
  7. @ComponentScan("com.jektong")
  8. public class PersonConfig {
  9. @Bean("person01")
  10. public Person person() {
  11. return new Person("李四",21);
  12. }
  13. }

测试,看是否扫描到这些注解所标注的类:PersonTest.java

  1. @Test
  2. public void test02() {
  3. ApplicationContext ac = new AnnotationConfigApplicationContext(PersonConfig.class);
  4. Person bean = ac.getBean(Person.class);
  5. System.out.println(bean);
  6. String[] beanDefinitionNames = ac.getBeanDefinitionNames();
  7. for (String string : beanDefinitionNames) {
  8. System.out.println(string);
  9. }
  10. }

测试效果:除了Spring要自动加载的配置类以外也显示了刚才添加的配置类:

图2

为何会出现PersonConfig,因为@Configuration本 身就是@Component注解的:

图3

@ComponentScan的扫描规则

如果需要指定配置类的扫描规则, @ComponentScan提供对应的扫描方式@Filter进行配置类的过滤:

  1. // 扫描包的时候只规定扫描一些注解配置类。
  2. Filter[] includeFilters() default {};
  3. // 扫描包的时候可以排除一些注解配置类。
  4. Filter[] excludeFilters() default {};

Filter其实也是一个注解,相当于@ComponentScan的子注解,可以看图4

图4

Filter对应的过滤规则如下:

第一种:扫描包的时候只规定扫描一些注解配置类【includeFilters】。

使用这个includeFilters过滤规则,必须解除默认的过滤规则,

使用【useDefaultFilters = false】

  1. package com.jektong.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.ComponentScan.Filter;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.context.annotation.FilterType;
  7. import org.springframework.stereotype.Controller;
  8. import com.jektong.spring.Person;
  9. @Configuration
  10. @ComponentScan(value = "com.jektong",includeFilters = {
  11. @Filter(type = FilterType.ANNOTATION,value= {Controller.class})
  12. },useDefaultFilters = false )
  13. public class PersonConfig {
  14. @Bean("person01")
  15. public Person person() {
  16. return new Person("李四",21);
  17. }
  18. }

这样就只会扫描用@Controller,标注的配置类交给Spring容器中了:

图5

 第二种:扫描包的时候可以排除一些注解配置类【excludeFilters 】。

图6

 @Filter看上图,有5种不同类型的过滤策略。拿第一种举例,我们需要过滤使用@Controller注解的配置类:

  1. package com.jektong.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.ComponentScan.Filter;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.context.annotation.FilterType;
  7. import org.springframework.stereotype.Controller;
  8. import com.jektong.spring.Person;
  9. @Configuration
  10. @ComponentScan(value = "com.jektong",excludeFilters = {
  11. @Filter(type = FilterType.ANNOTATION,value= {Controller.class})
  12. } )
  13. public class PersonConfig {
  14. @Bean("person01")
  15. public Person person() {
  16. return new Person("李四",21);
  17. }
  18. }

测试看一下发现图2中的personController不会交给Spring容器去管理了:

图7

上面的图6展示出5种不同类型的过滤策略,上面介绍了注解类型(FilterType.ANNOTATION),还有四种: 

重点看一下CUSTOM自定义扫描策略。

 

从源码看,自定义扫描注解类型需要实现TypeFilter接口,下面就写一个实现类MyFilter.java:在实现类中可以自定义配置规则:

  1. package com.jektong.config;
  2. import java.io.IOException;
  3. import org.springframework.core.io.Resource;
  4. import org.springframework.core.type.AnnotationMetadata;
  5. import org.springframework.core.type.ClassMetadata;
  6. import org.springframework.core.type.classreading.MetadataReader;
  7. import org.springframework.core.type.classreading.MetadataReaderFactory;
  8. import org.springframework.core.type.filter.TypeFilter;
  9. public class MyFilter implements TypeFilter {
  10. @Override
  11. public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
  12. throws IOException {
  13. // 查看当前类的注解。
  14. AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
  15. // 查看当前扫描类的信息
  16. ClassMetadata classMetadata = metadataReader.getClassMetadata();
  17. // 获取当前类资源
  18. Resource resource = metadataReader.getResource();
  19. String className = classMetadata.getClassName();
  20. System.out.println("className===>" + className);
  21. // 只要类名包含er则注册Spring容器
  22. if(className.contains("er")) {
  23. return true;
  24. }
  25. return false;
  26. }
  27. }

测试:

PersonConfig 中进行扫描:

  1. package com.jektong.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.ComponentScan.Filter;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.context.annotation.FilterType;
  7. import org.springframework.stereotype.Controller;
  8. import com.jektong.service.PersonService;
  9. import com.jektong.spring.Person;
  10. @Configuration
  11. @ComponentScan(value = "com.jektong",includeFilters = {
  12. @Filter(type = FilterType.CUSTOM,value= {MyFilter.class})
  13. },useDefaultFilters = false )
  14. public class PersonConfig {
  15. @Bean("person01")
  16. public Person person() {
  17. return new Person("李四",21);
  18. }
  19. }

可以看出扫描出包下面的类只要带“er”的全部扫描出来,并配置给Spring容器:

ASSIGNABLE_TYPE:按照指定的类型去加载对应配置类:

  1. package com.jektong.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.ComponentScan.Filter;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.context.annotation.FilterType;
  7. import org.springframework.stereotype.Controller;
  8. import com.jektong.service.PersonService;
  9. import com.jektong.spring.Person;
  10. @Configuration
  11. @ComponentScan(value = "com.jektong",includeFilters = {
  12. @Filter(type = FilterType.ASSIGNABLE_TYPE,value= {PersonService.class})
  13. },useDefaultFilters = false )
  14. public class PersonConfig {
  15. @Bean("person01")
  16. public Person person() {
  17. return new Person("李四",21);
  18. }
  19. }

尽管我们将PersonService.java上的注解去掉,使用ASSIGNABLE_TYPE依然会加载出来(自行测试)。

ASPECTJ与REGEX基本不用,不用了解。

以上就是@ComponentScan的具体用法,该兴趣的话可以看一下源码。

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发