factorybean 代理类不能按照类型注入_Spring注解驱动开发之四——@Import快速导入组件、FactoryBean 定义工厂注册组件...

f9c82d250a5de8271b8a786d18185c65.png

本文包含以下内容:

  1. @Import快速导入组件

  2. 配合ImportSelector 导入组件

  3. 配合ImportBeanDefinitionRegistrar 导入组件

  4. FactoryBean 定义工厂注册组件

1.@Import快速导入组件

在前几篇推文中,通过@Bean 标记在方法上,手动new 一个实例注入到容器中,这种方法,会比较繁琐,需要手动编写过多无意义代码
  @Bean("bill")  public Person person01(){    return new Person("Bill Gates",62);  }
通过@Import,方法可以不需要编写构造方法,快速注册组件1)建立测试类
public class Color {}public class Red  {  }public class Blue {  }public class Yellow {}
2)使用@Import({Color.class,Red.class})  导入类组件
@Import({Color.class,Red.class})public class MainConfig2 {}
3)编写测试方法
@Testpublic void testImport(){  printBeans(applicationContext);  Blue bean = applicationContext.getBean(Blue.class);  System.out.println(bean);}private void printBeans(AnnotationConfigApplicationContext applicationContext){  String[] definitionNames = applicationContext.getBeanDefinitionNames();  for (String name : definitionNames) {    System.out.println(name);  }}
4)运行测试,可以看到@Import注解创建的组件默认以全类名作为id 的形式注入到容器中

f09bcb6ee21034f23bed8eb100c4f8f8.png

2.配合ImportSelector 导入组件

在@Import注解 中还能添加ImportSelector

d54b0ace014077a4f7e131e4fc563062.png

查看源码,看到这个接口需要实现selectImports 返回类的全类名即可:

5e625a1d1a591ed08d9d77abfad56576.png

1)创建Selector
//自定义逻辑返回需要导入的组件public class MyImportSelector implements ImportSelector {  //返回值,就是到导入到容器中的组件全类名  //AnnotationMetadata:当前标注@Import注解的类的所有注解信息  @Override  public String[] selectImports(AnnotationMetadata importingClassMetadata) {    // TODO Auto-generated method stub    //importingClassMetadata    //方法不要返回null值    return new String[]{"peason.zxc.annotation.bean.Blue","peason.zxc.annotation.bean.Yellow"};  }}
2)在注解中引入Selector
@Import({Color.class, Red.class,MyImportSelector.class})
3)获得测试结果,能够注入"peason.zxc.annotation.bean.Blue","peason.zxc.annotation.bean.Yellow"等组件

c691a2fc44d99955b9af1785b234e513.png

3.配合ImportBeanDefinitionRegistrar 导入组件

在@Import注解中还能添加ImportSelector

050f6366f964e36a2176dfd2d10e05cf.png

1)建立自定义的实现类其中有2个参数:AnnotationMetadata:当前类的注解信息
BeanDefinitionRegistry :当前容器的注册入口,可以直接注册组件下面例子是如果注册器内存在Red 、Blue 的组件,就进行创建rainBow 实例,此处id 累哦自定义名称
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {  /**   * AnnotationMetadata:当前类的注解信息   * BeanDefinitionRegistry:BeanDefinition注册类;   *     把所有需要添加到容器中的bean;调用   *     BeanDefinitionRegistry.registerBeanDefinition手工注册进来   */  @Override  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {    boolean definition = registry.containsBeanDefinition("peason.zxc.annotation.bean.Red");    boolean definition2 = registry.containsBeanDefinition("peason.zxc.annotation.bean.Blue");    if(definition && definition2){      //指定Bean定义信息;(Bean的类型,Bean。。。)      RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);      //注册一个Bean,指定bean名      registry.registerBeanDefinition("rainBow", beanDefinition);    }  }}
2)在注解中引入
@Import({Color.class, Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
3)测试结果,成功根据条件注入了id 为rainBow的组件

aea30dccdb7d795773082d211675eaa6.png

4.FactoryBean 定义工厂注册组件

在@Import注解,会调用默认的无参构造器创建对象,而注入容器FactoryBean 的主键会默认调用,这个接口的getObject()返回实例进行组件的创建。下面进行测试:1)创建实现FactoryBean 接口的类
//创建一个Spring定义的FactoryBeanpublic class ColorFactoryBean implements FactoryBean {  //返回一个Color对象,这个对象会添加到容器中  @Override  public Color getObject() throws Exception {    // TODO Auto-generated method stub    System.out.println("ColorFactoryBean...getObject...");    return new Color();  }  @Override  public Class> getObjectType() {    // TODO Auto-generated method stub    return Color.class;  }  //是单例?  //true:这个bean是单实例,在容器中保存一份  //false:多实例,每次获取都会创建一个新的bean;  @Override  public boolean isSingleton() {    // TODO Auto-generated method stub    return false;  }}
2)通过@Bean 将工厂注入到容器中
  @Bean  public ColorFactoryBean colorFactoryBean(){    return new ColorFactoryBean();  }
3)编写测试方法
  @Test  public void testImport(){    printBeans(applicationContext);    //工厂Bean获取的是调用getObject创建的对象    Object bean2 = applicationContext.getBean("colorFactoryBean");    Object bean3 = applicationContext.getBean("colorFactoryBean");    System.out.println("bean的类型:"+bean2.getClass());    System.out.println(bean2 == bean3);    Object bean4 = applicationContext.getBean("&colorFactoryBean");    System.out.println(bean4.getClass());  }
4)获得结果

c724ea7034901749c032400226cf2cfa.png

5)分析结果:1.在打印所有的组件可以看到colorFactoryBean 组件通过获取,多次可以看到,2次获取结果并非同一个实例对象,由此见得,在方法isSingleton 生效了,采用多实例构建
//是单例?  //true:这个bean是单实例,在容器中保存一份  //false:多实例,每次获取都会创建一个新的bean;  @Override  public boolean isSingleton() {    // TODO Auto-generated method stub    return false;  }
2.通过该id 获取该组件,获取到bean 的类型为peason.zxc.annotation.bean.Color 由此可见,获取对象时通过调用getObject函数创建组件
//返回一个Color对象,这个对象会添加到容器中  @Override  public Color getObject() throws Exception {    // TODO Auto-generated method stub    System.out.println("ColorFactoryBean...getObject...");    return new Color();  }
3.可以通过&符号获取到FactoryBean 对象即最后的结果class peason.zxc.annotation.bean.ColorFactoryBean,可以看到源码所示,指定了&符号

0554add1edcb67c3afb1d7d456df9088.png

-END-

c07fa61b41d5d012bfc5b26b4d04c3f7.png

可以关注我的公众号,免费获取价值1980元学习资料

点击“在看”,学多少都不会忘~

347c2e87892a2646de1ad7a42effdeea.png


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部