Spring中给IoC容器注入bean的几种方法(二)

由于文章比较长,一次发不出去,分开来发,前面两种方法请查看《Spring中给IoC容器注入bean的几种方法(一)

3、@Import注解导入类

  除了用@Bean和@ComponentScan类将bean注入到spring容器中,@Import类也可以实现对应的功能,其使用方法如下:

3.1 用@Import注解导入指定的类

  @Import注解可以导入指定的类到spring容器中,这个类可以不加任何的主机,只是一个单纯的java对象,示例代码如下:

  • 首先创建一个测试类ImportTest,用来打印出spring容器中我们关注的bean对象
public class ImportTest {

    @Test
    public void showIocComponents() {
        ApplicationContext context = new AnnotationConfigApplicationContext(ImportConfig.class);
        System.out.println("-----------------容器启动完成---------------------");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            //跳过spring的 bean和配置bean本身,只关注我们自己定义的对象
            if (beanDefinitionName.contains("org.springframework.context")
                    || beanDefinitionName.endsWith("Config")) {
                continue;
            }
            System.out.println(beanDefinitionName);
        }
    }
}
  • 我们在entities包下编写几个bean对象,用来测试使用
public class Cat {
}
public class Joms {
}
public class TomCat {
}
public class BeatMouse {
}
  • 编写ImportConfig类,用@Import注解导入一个Cat对象
@Configuration
@Import({Cat.class})
public class ImportConfig {
}

  • 测试结果如下:
-----------------容器启动完成---------------------
entities.Cat

3.2 用@Import注解导入其他@Configuration标注的配置类

  @Import注解可以导入其他的@Configuration标注的配置类,并将配置类中的配置也导入进来。这是springBoot框架中常用的一种方式,这样的好处是将配置进行了分类,再利用@Conditional注解完成了自动装配的功能。示例代码如下:

  • 编写一个@Configuration标注的配置类,这个配置类中用@Bean注解加入了一个Joms对象
@Configuration
public class OtherImportConfig {

    @Bean
    public Joms joms(){
        return new Joms();
    }
}
  • 在ImportConfig中用@Import注解将OtherImportConfig配置类导入进来
@Configuration
@Import({OtherImportConfig.class})
public class ImportConfig {
}
  • 测试结果如下:
-----------------容器启动完成---------------------
joms

  从上面结果中可以看出,@Import注解将另一个配置类中的配置也导入到了spring容器中。

3.3 用@Import注解导入ImportSelector的类

  @Import注解还可以导入自定义的全路径的类,在实现的过程中,我们首先要创建一个实现了org.springframework.context.annotation.ImportSelector结构的类,并将需要导入到容器中的类在方法selectImports中用全类名的方式返回,这样spring就可以帮我们将其中的类导入到容器中。示例代码如下:

  • 首先编写一个ImportSelector类,将要导入的TomCat对象的全类名进行返回
public class ImportSelector implements org.springframework.context.annotation.ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"entities.TomCat"};
    }
}
  • 在ImportConfig中用@Import注解将ImportSelector 类导入进来
@Configuration
@Import({ImportSelector.class})
public class ImportConfig {
}
  • 测试结果如下:
-----------------容器启动完成---------------------
entities.TomCat

3.4 用@Import注解导入自定义的ImportBeanDefinitionRegistrar对象

  可以在@Import注解中导入自定义的BeanDefinition对象,具体的实现是创建一个实现了org.springframework.context.annotation.ImportBeanDefinitionRegistrar接口的类,在 registerBeanDefinitions方法中创建或者修改对应的BeanDefinition,示例代码如下:

  • 创建一个ImportBeanDefinitionRegistrar的实现类MyImportBeanDefinitionRegistrar,并将BeatMouse对象加入到容器中
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        BeanDefinition beanDefinition = new RootBeanDefinition(BeatMouse.class);
        beanDefinitionRegistry.registerBeanDefinition("beatMouse",beanDefinition);
    }
}
  • 在ImportConfig中用@Import注解将MyImportBeanDefinitionRegistrar 类导入进来
@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
public class ImportConfig {
}
  • 测试结果如下:
-----------------容器启动完成---------------------
beatMouse

4、FactoryBean 把需要注入的对象封装为FactoryBean

  在spring中,FactoryBean和BeanFactory是两个非常容易混淆的概念,我们在这里先做个澄清。

  • FactoryBean :工厂Bean,本质上还是一个Bean,负责将Bean注入到容器的Bean
  • BeanFactory :Bean的工厂,是一个创建Bean的工厂, 从IoC中获得Bean对象
      FactoryBean 导入bean的 方式比较特殊,使用的场景也比较少,这种方式主要是用于需要导入的对象比较特殊,需要复杂的创建过程的对象。在具体的实现中,我们需要编写一个实现了org.springframework.beans.factory.FactoryBean接口的工厂bean的对象,将需要具体创建的对象用这个工厂bean来创建,然后将这个工厂bean注入到spring的容器中,在我们用getBean方法获取对象时,正常我们获取到的是由工厂bean创建出来的产品对象,而不是工厂bean本身,如果需要获取工厂bean本身,我们需要在getBean方法的名称前面加上"&"符,示例如下:
  • 编写一个真正需要创建的对象Monkey
public class Monkey {
}
  • 编写一个工厂bean对象MonkeyFactoryBean,用来创建Monkey对象
public class MonkeyFactoryBean implements FactoryBean<Monkey> {
    @Override
    public Monkey getObject() throws Exception {
        return new Monkey();
    }

    @Override
    public Class<?> getObjectType() {
        return Monkey.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
  • 编写一个配置类,并将MonkeyFactoryBean注入到容器中
@Configuration
public class FactoryBeanConfig {

    @Bean
    public MonkeyFactoryBean monkey() {
        return new MonkeyFactoryBean();
    }
}
  • 编写一个测试类
public class FactoryBeanTest {

    @Test
    public void showIocComponents() {
        ApplicationContext context = new AnnotationConfigApplicationContext(FactoryBeanConfig.class);
        System.out.println("-----------------容器启动完成---------------------");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            //跳过spring的 bean和配置bean本身,只关注我们自己定义的对象
            if (beanDefinitionName.contains("org.springframework.context")
                    || beanDefinitionName.endsWith("Config")) {
                continue;
            }
            System.out.println(beanDefinitionName);
        }
        System.out.println("----直接获取factoryBean的对象-----");
        System.out.println(context.getBean("monkey"));
        System.out.println("----获取factoryBean的工厂对象-----");
        System.out.println(context.getBean("&monkey"));
    }
}

测试结果如下:

-----------------容器启动完成---------------------
monkey
----直接获取factoryBean的对象-----
entities.Monkey@e50a6f6
----获取factoryBean的工厂对象-----
config.factorybean.MonkeyFactoryBean@14ec4505

  从上面的测试结果可以看出,我们注入到spring中的是FactoryBean对象,但是实际用getBean方法获取的是创建出来的具体对象。

总结

  本文总结了Spring中给IoC容器注入bean的几种方法,在这些方法中,有些是我们平常常用的,有些可能不怎么常见,不常见的这些并不代表其没有使用场景,这些主要是用于一些框架或者大型相互关联的项目中,如果深入研究过Spring和SpringBoot的源码,相信我们就会对这些方法并不感到陌生了。


后记
  个人总结,欢迎转载、评论、批评指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值