Spring注解开发之@Bean和@ComponentScan

组件注册

用@Bean来注册

  1. 搭建好maven web工程

  2. pom加入spring-context,spring-core等核心依赖

  3. 创建实例类com.hjj.bean.Person, 生成getter,setter方法

    public class Person {
        private String name;
        private int age;
    }
    
  4. 创建com.hjj.config.MainConfig

    @Configuration   //告诉spring是一个配置类
    public class MainConfig {
    
        // 给容器中注册一个Bean,类行为返回值的类型,id默认是用方法名作为id
        @Bean("mikePerson")
        public Person person(){
            return new Person("mike",20);
        }
    }
    
  5. 主测试类

    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            Person bean = applicationContext.getBean(Person.class);
            System.out.println(bean);
    
            String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
            for (String type : beanNamesForType) {
                System.out.println(type);  //配置类中的方法名,注意:通过修改配置类的@bean value也可以修改
            }
        }
    }
    

@ComponentScan包扫描

  1. 配置类中MainConfig.java

    @Configuration   //告诉spring是一个配置类
    @ComponentScan("com.hjj") // 扫描包的路径
    public class MainConfig {
    
        // 给容器中注册一个Bean,类行为返回值的类型,id默认是用方法名作为id
        @Bean("mikePerson")
        public Person person(){
            return new Person("mike",20);
        }
    }
    
    
  2. 新建测试的com.hjj.controller,service,dao

    @Controller
    public class BookController {
    }
    
    @Repository
    public class BookDao {
    }
    
    @Service
    public class BookService {
    }
    
  3. 单元测试

        @Test
        public void test01(){
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); //获取所有组件
            for (String beanDefinitionName : beanDefinitionNames) {
                System.out.println(beanDefinitionName);  
            }
        }
    
    
  • ComponentScan字段,有includeFilter(),和excludeFilter() 只包含或排除某些组件

    @ComponentScan(value = "com.hjj",excludeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})})
    @ComponentScan(value = "com.hjj",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})},userDefaultFilters=false)
    
    // excludeFilter源码
    ComponentScan.Filter[] excludeFilters() default {}; 
    
    // ComponentScan.Filter源码
    @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 {};
    }
    
  • @ComponentScan被@Repeatable(ComponentScans.class),可以重复写,用来写不同的执行策略。

  • @ComponentScans 里面可以放ComponentScan类型的值

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @Documented
    public @interface ComponentScans {
        ComponentScan[] value();
    }
    
  • FilterType

    public enum FilterType {
        ANNOTATION,   // 按注解扫描
        ASSIGNABLE_TYPE, // 按给定的类型
        ASPECTJ,  // 可以用aspectJ表达式
        REGEX,  // 正则表达式
        CUSTOM; // 自定义规则
    
        private FilterType() {
        }
    }
    
    • ASSIGNABLE_TYPE

      @ComponentScan(value = "com.hjj",
      includeFilters ={@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes = {BookService.class})})
      
      // config配置如上注解后 bookservice,可以被发现
          @Test
          public void demoTest1(){
              AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
              String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
              for (String beanDefinitionName : beanDefinitionNames) {
                  System.out.println(beanDefinitionName);
              }
          }
      
      
      
    • Custom 可以自定义配置或写业务扫描类的信息,match返回true则是加到组件

      1.复写TypeFilter的match方法
      public class MyTypeFilter implements TypeFilter {
      
          /**
           *
           * @param metadataReader 读取到的当前正在扫描的类的信息
           * @param metadataReaderFactory 可以获取到其他任何类信息
           * @return
           * @throws IOException
           */
          @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);
              return false;
          }
      }
      
      2. 加上注解
      @Configuration   //告诉spring是一个配置类
      @ComponentScan(value = "com.hjj",
      includeFilters ={
              @ComponentScan.Filter(type=FilterType.CUSTOM,classes = {MyTypeFilter.class})},
              useDefaultFilter=false)
      public class MainConfig {
      
      }
      
      @Test
      public void test01(){
      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
      String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
      for (String beanDefinitionName : beanDefinitionNames) {
      System.out.println(beanDefinitionName);
      }
      }
      
      结果
      className:com.hjj.test.IOCTest
      className:com.hjj.MainTest
      className:com.hjj.bean.Person
      className:com.hjj.config.MyTypeFilter
      className:com.hjj.demo.DemoTest
      className:com.hjj.demo.Employee
      className:com.hjj.demo.Manager
      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
      mainConfig
      
posted @ 2020-08-23 16:09  Jimmyhe  阅读(537)  评论(0编辑  收藏  举报