【spring注解驱动开发】- 组件注册 - @Import&FactoryBean

文章目录

  • 1 对前几篇博客的一个小总结
  • 2 @Import
    • 2.1 @Import(组件的类型)
    • 2.2 @Import(ImportSelector) 的方式
    • 2.3 @Import(ImportBeanDefinitionRegistrar) 的方式
  • 3 FactoryBean

本博客demo源码地址
https://github.com/suchahaerkang/spring-annotation.git

1 对前几篇博客的一个小总结

  • 目前我们知道了两种方式注册组件
    • 通过注解@ComponentScan + 组件上标注@Controller,@Service, @Repository和@Component的方式注册 ,但是这种方法有个弊端,就是这能注册我们自己编写的类,如果第三方组件没有加上@Controller这些注解的话,又该怎么注册组件呢?
    • 通过@Bean的方式注册,这种方式就可以解决上面不能注册第三方组件的问题
  • 另外还有两种注册方式
    • @Import注解的方式
    • spring自定义的FactoryBean的方式

下面我们就来学习一下下面两种方式注册组件

2 @Import

2.1 @Import(组件的类型)

这种方式是默认方式,可以将第三方组件快速注册到容器中,在容器中的id默认为全类名
首先我们创建一个Red类当作第三方组件

	/**
	 * @description:
	 * @author: sukang
	 * @date: 2020-03-05 15:18
	 */
	public class Red {
	}

测试用例

 	@Test
    public void test05(){
        //创建容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        //获取IOC容器中的所有组件名
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String name :beanNames) {
            System.out.println(name);
        }
    }

运行结果
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第1张图片

2.2 @Import(ImportSelector) 的方式

ImportSelector 是spring提供的一个接口,实现这个接口的selectImports()方法,我们可以自定义返回需要注册的组件的全类名,我们自定义一个实现ImportSelector 接口的类,将新创建的Blue和Yellow类的全类名封装成为一个数组返回

	/**
	 * @description:
	 * @author: sukang
	 * @date: 2020-03-05 15:44
	 */
	public class MyImportSelector implements ImportSelector {
	
	    /**
	     * @description:
	     * @param importingClassMetadata 当前注解@Import标注的类上面的全部注解信息
	     * @return: java.lang.String[]
	     * @author: sukang
	     * @date: 2020/3/5 15:45
	     */
	    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
	        String[] str = new String[]{"com.wolfx.bean.Blue","com.wolfx.bean.Yellow"};
	        return str;
	    }
	}

将该实现类加到@Import注解里面去
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第2张图片
测试用例

	@Test
    public void test05(){
        //创建容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        //获取IOC容器中的所有组件名
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String name :beanNames) {
            System.out.println(name);
        }
    }

运行结果
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第3张图片
这种方式注册的组件在容器中的id也是全类名,这种方式在springboot中用到的比较多,理解这种方式有助于我们理解springboot里面相关的知识

2.3 @Import(ImportBeanDefinitionRegistrar) 的方式

ImportBeanDefinitionRegistrar也是spring提供的一个接口,如果实现这个接口的registerBeanDefinitions()方法,我们可以利用这个方法的一个参数BeanDefinitionRegistry进行手动注册组件到容器中去,我们写一个实现类

	/**
     * @description:
     * @param importingClassMetadata  当前注解@Import标注的类的所有注解信息
     * @param registry 组件信息注册中心,通过它可以手动注册组件
     * @return: void
     * @author: sukang
     * @date: 2020/3/5 16:04
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //判断容器中是否有Blue和Yellow的组件
        Boolean boolean1 = registry.containsBeanDefinition("com.wolfx.bean.Blue");
        Boolean boolean2 = registry.containsBeanDefinition("com.wolfx.bean.Yellow");

        if(boolean1 && boolean2){
            //定义一个RainBow组件信息,这里也可以指定一个组件的作用域
            BeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
            //将RainBow组件信息注册到容器中去,在容器中的id为rainBow
            registry.registerBeanDefinition("rainBow", beanDefinition);
        }

    }

然后将这个类写到@Import中去
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第4张图片
测试用例

 	@Test
    public void test05(){
        //创建容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        //获取IOC容器中的所有组件名
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String name :beanNames) {
            System.out.println(name);
        }
    }

运行结果
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第5张图片

3 FactoryBean

FactoryBean是Spring提供的特殊bean接口,实现它的类要重写getObject(),getObjectType()方法。其他三种组件注册方法,都是将组件注册到容器中去,然后通过调用组件的构造函数创建的实例,而FactoryBean这种方式是通过调用getObject()方法来创建组件。我们自定义一个实现FactoryBean接口的类

	/**
	 * @description:
	 * @author: sukang
	 * @date: 2020-03-05 16:26
	 */
	public class WhiteFactoryBean implements FactoryBean<White> {
	
	    //FactoryBean 是通过这个方法将组件添加到容器中的
	    public White getObject() throws Exception {
	        return new White();
	    }
	
	    public Class<?> getObjectType() {
	        return White.class;
	    }
	
	    //true:为单实例
	    //false:为多实例
	    public boolean isSingleton(){
	        return true;
	    }
	}

在配置类中配置将WhiteFactoryBean注册到容器中

 	@Bean
    public WhiteFactoryBean whiteFactoryBean(){
        return new WhiteFactoryBean();
    }

测试用例

	@Test
    public void test06() throws Exception {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        System.out.println(applicationContext.getBean("whiteFactoryBean"));
    }

运行结果
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第6张图片
通过运行结果我们可以看到从容器中获取id为whiteFactoryBean的对象并不是WhiteFactoryBean组件的实例,而是White组件的实例,那么我们怎么才能获取到WhiteFactoryBean类的实例呢?通过看源码我们可知需要在id前面加上一个&
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第7张图片
测试用例

   	@Test
    public void test06() throws Exception {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        System.out.println(applicationContext.getBean("&whiteFactoryBean"));
    }

运行结果
【spring注解驱动开发】- 组件注册 - @Import&FactoryBean_第8张图片

你可能感兴趣的:(spring)