笔记来源:01-Import 注册组件 - 图1尚硅谷Spring注解驱动教程(雷丰阳源码级讲解)

Import 注册组件

1、@Import

  • 1)包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)【局限于自己编写的组件】
  • 2)@Bean【导入的第三方包中的组件】
  • 3)@Import【快速给容器中导入一个组件】

    • 1)@Import(要导入到容器中的组件):容器中会自动注册这个组件,id 默认是全类名
    • 2)ImportSelector:返回需要导入的组件的全类名数组
    • 3)ImportBeanDefinitionRegistrar:手动注册 Bean 到容器中

Import 注解源码解析

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface Import {
  5. /**
  6. * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
  7. * or regular component classes to import.
  8. */
  9. Class<?>[] value();
  10. }

@Import 只能作用于类上,可以传入“一组” Class 类

  • 可以是需要导入到容器中的组件 Bean
  • 可以是 ImportSelector 实现类
  • 可以是 ImportBeanDefinitionRegistrar 实现类

ImportSelector 接口源码解析

  1. public interface ImportSelector {
  2. String[] selectImports(AnnotationMetadata importingClassMetadata);
  3. }

其中定义一个 selectImports 方法,提供了一个入参

  • AnnotationMetadata:可以获取当前类的注解信息

    • getAnnotationTypes:获取注解类型集合
    • getMetaAnnotationTypes:获取元注解类型集合
    • hasAnnotation:是否有某个注解
    • hasMetaAnnotation:是否有某个元注解
    • hasAnnotatedMethods:是否有注解方法
    • getAnnotatedMethods:获取注解方法集合
  1. public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
  2. Set<String> getAnnotationTypes();
  3. Set<String> getMetaAnnotationTypes(String annotationName);
  4. boolean hasAnnotation(String annotationName);
  5. boolean hasMetaAnnotation(String metaAnnotationName);
  6. boolean hasAnnotatedMethods(String annotationName);
  7. Set<MethodMetadata> getAnnotatedMethods(String annotationName);
  8. }

ImportBeanDefinitionRegistrar 接口源码解析

  1. public interface ImportBeanDefinitionRegistrar {
  2. public void registerBeanDefinitions(
  3. AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
  4. }

其中定义一个 registerBeanDefinitions 方法,提供了两个入参

  • AnnotationMetadata:可以获取当前类的注解信息
  • BeanDefinitionRegistry:可以向容器中注册一个 Bean

    • registerBeanDefinition:注册组件
    • removeBeanDefinition:移除组件
    • getBeanDefinition:获取组件
    • containsBeanDefinition:是否包含组件
    • getBeanDefinitionNames:获取组件名
    • getBeanDefinitionCount:获取组件数
    • isBeanNameInUse:组件是否使用
  1. public interface BeanDefinitionRegistry extends AliasRegistry {
  2. void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
  3. void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
  4. BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
  5. boolean containsBeanDefinition(String var1);
  6. String[] getBeanDefinitionNames();
  7. int getBeanDefinitionCount();
  8. boolean isBeanNameInUse(String var1);
  9. }

2、测试

实体类

  1. public class Red {}
  2. public class Yellow {}
  3. public class Green {}
  4. public class Blue {}
  5. public class Rainbow {}

配置类

  1. @Configuration
  2. @Import({Red.class, Yellow.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
  3. public class SpringConfig4 {}

自定义导入选择器

  1. public class MyImportSelector implements ImportSelector
  2. {
  3. @Override
  4. public String[] selectImports(AnnotationMetadata importingClassMetadata) {
  5. return new String[] {Green.class.getName(), Blue.class.getName()};
  6. }
  7. }

自定义导入 Bean 定义注册器

  1. public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
  2. {
  3. @Override
  4. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  5. boolean beanDefinition1 = registry.containsBeanDefinition(Red.class.getName());
  6. boolean beanDefinition2 = registry.containsBeanDefinition(Green.class.getName());
  7. boolean beanDefinition3 = registry.containsBeanDefinition(Blue.class.getName());
  8. if (beanDefinition1 && beanDefinition2 && beanDefinition3) {
  9. BeanDefinition beanDefinition = new RootBeanDefinition(Rainbow.class);
  10. registry.registerBeanDefinition("rainbow", beanDefinition);
  11. }
  12. }
  13. }

测试类

  1. public class SpringAnnotationTest4
  2. {
  3. private ApplicationContext context;
  4. @Before
  5. public void initContext() {
  6. context = new AnnotationConfigApplicationContext(SpringConfig4.class);
  7. }
  8. @Test
  9. public void testImport() {
  10. String[] names = context.getBeanDefinitionNames();
  11. for (String name : names) {
  12. System.out.println(name);
  13. }
  14. System.out.println("===============");
  15. Red red = context.getBean(Red.class.getName(), Red.class);
  16. Yellow yellow = context.getBean(Yellow.class.getName(), Yellow.class);
  17. Green green = context.getBean(Green.class.getName(), Green.class);
  18. Blue blue = context.getBean(Blue.class.getName(), Blue.class);
  19. Rainbow rainbow = context.getBean("rainbow", Rainbow.class);
  20. System.out.println(red);
  21. System.out.println(yellow);
  22. System.out.println(green);
  23. System.out.println(blue);
  24. System.out.println(rainbow);
  25. }
  26. }

测试结果

  1. org.springframework.context.annotation.internalConfigurationAnnotationProcessor
  2. org.springframework.context.annotation.internalAutowiredAnnotationProcessor
  3. org.springframework.context.annotation.internalRequiredAnnotationProcessor
  4. org.springframework.context.annotation.internalCommonAnnotationProcessor
  5. org.springframework.context.event.internalEventListenerProcessor
  6. org.springframework.context.event.internalEventListenerFactory
  7. springConfig4
  8. com.vectorx.springannotation.entity.Red
  9. com.vectorx.springannotation.entity.Yellow
  10. com.vectorx.springannotation.entity.Green
  11. com.vectorx.springannotation.entity.Blue
  12. rainbow
  13. ===============
  14. com.vectorx.springannotation.entity.Red@ca263c2
  15. com.vectorx.springannotation.entity.Yellow@589b3632
  16. com.vectorx.springannotation.entity.Green@45f45fa1
  17. com.vectorx.springannotation.entity.Blue@4c6e276e
  18. com.vectorx.springannotation.entity.Rainbow@534df152