Spring注解(五) @Import

133 阅读2分钟

@Import

import用法1

  • 这是一种比较简单的向ioc容器导入组件的方法 在配置类上写上需要导入的类即可, 注意这样使用Color需要是无参构造
@Configuration
@Import(Color.class)
public class ImportConfig {
}
  • 测试
  @Test
  void testImport() {
      AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(ImportConfig.class);
      String[] beans = ioc.getBeanDefinitionNames();
      for (String bean : beans) {
          System.out.println(bean);
      }
  }

ImportSelector

  • ImportSelector 导入选择器 配置
@Configuration
@Import(MyImportSelector.class)
public class ImportSelectorConfig {
}
  • 配置MyImportSelector
public class MyImportSelector implements ImportSelector {
    /**
     *
     * @param importingClassMetadata 元注解
     * @return
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        String[] arr = new String[8];
        arr[0] = "com.alex.person.Color"; //这里写要注入的类的全类名,
        return arr;
    }
}
  • 测试
    @Test
    void testImportSelector() {
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(ImportSelectorConfig.class);
        String[] beans = ioc.getBeanDefinitionNames();
        for (String bean : beans) {
            System.out.println(bean);
        }
    }

小结: 重写selectImports是自动配置类的核心原理了, 自动配置就是通过重写这个方法, 把所有全类名注入的.

实现ImportBeanDefinitionRegistrar接口

  • 手工注册 测试代码
  1. 实现ImportBeanDefinitionRegistrar接口
  2. 逻辑是如果存在"red"或者"com.alex.person.Color"这两个bean就将名为"rainbow"的bean注册到容器中
public class MyImportBeanRegisterar implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata 当前类的注解信息
     * @param registry 所以bean的定义都在这注册
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean definition = registry.containsBeanDefinition("red");
        boolean definition2 = registry.containsBeanDefinition("com.alex.person.Color");

        if (definition || definition2) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Rainbow.class);
            registry.registerBeanDefinition("rainbow", beanDefinition);
        }
    }
}
@Configuration
@Import({MyImportBeanRegisterar.class})
public class ImportSelectorConfig {
}

使用FactoryBean

特点

  • 是个接口
  • 会调用这个接口的getObject方法创建对象加入容器.

使用方法

  • 实现接口FactoryBean
  • 注入容器
public class ColorFactory implements FactoryBean<Color> {
    @Override
    public Color getObject() throws Exception {
        return new Color(); // 注入的对象
    }

    @Override
    public Class<?> getObjectType() {
        return Color.class; // 注入的类型
    }

    @Override
    public boolean isSingleton() {
        return false; // 是否单例
    }
}
  • 编写注入ColorFactory的方法
@Configuration
public class ColorFactoryConfig {
    @Bean
    public ColorFactory colorFactory() {
        return new ColorFactory();
    }
}
  • 测试
    @Test
    void testFactoryBean() {
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(ColorFactoryConfig.class);
        String[] beans = ioc.getBeanDefinitionNames();
        for (String bean : beans) {
            System.out.println(bean);
        }

        Object colorFactory = ioc.getBean("colorFactory");//获取
        System.out.println(colorFactory.getClass());
    }
  • 结果 看着是向容器中导入了工厂bean, 实际调用工厂创建了对象加入了ioc容器
colorFactoryConfig
colorFactory
class com.alex.person.Color //居然注入了Color
  • 获取工厂本身 给beanid 前面加 '&' "&colorFactory"
    @Test
    void testFactoryBean() {
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(ColorFactoryConfig.class);
        String[] beans = ioc.getBeanDefinitionNames();
        for (String bean : beans) {
            System.out.println(bean);
        }

        Object colorFactory = ioc.getBean("&colorFactory");//获取工厂本身
        System.out.println(colorFactory.getClass());
    }
  • 结果
colorFactoryConfig
colorFactory
class com.alex.import2.ColorFactory