7、使用FactoryBean注册组件
工厂Bean。此Bean非常的重要,因为第三方框架要和Spring整合,大都是通过实现此接口来实现的。
public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); default boolean isSingleton() { return true; } }
举个例子,我自己来实现这个Bean接口:
public class ColorFactoryBean implements FactoryBean<Color> { // 返回一个Color对象 @Override public Color getObject() throws Exception { return new Color(); } @Override public Class<?> getObjectType() { return Color.class; } // 是否为单例 @Override public boolean isSingleton() { return true; } }
通过@Bean注入到容器里:
@Bean public ColorFactoryBean colorFactoryBean() { return new ColorFactoryBean(); }
测试一下:
@Test public void test05() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); Object bean = applicationContext.getBean("colorFactoryBean"); // 工厂bean调用的是getClass()方法 System.out.println("colorFactoryBean的类型是: " + bean.getClass()); }
输出一下,发现此时的bean调用的方法是getObjectType方法输出为:class com.fsx.boot2demo1.bean.Color
如果需要获取FactoryBean本身,可以在id前面加一个“&”标识
Object bean2 = applicationContext.getBean("&colorFactoryBean");
这个时候输出的就是:com.fsx.boot2demo1.bean.ColorFactoryBean
抛出一个问题:为何不直接使用@Bean,而使用FactoryBean呢?
Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean 即 FactoryBean。FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。创建出来的对象是否属于单例由isSingleton中的返回决定。
官方解释:
FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。
我的解释:
简单的说:它是用来处理复杂的Bean,在初始化过程中需要做很多事情(比如MyBatis的SqlSessionFactoryBean等等),从而屏蔽内部实现,对调用者/使用者友好的一种解决方案。
如果这种Bean用xml去配置,几乎是不可能的。当用注解驱动@Bean去做后,虽然也是可以的,但是很显然对调用很不友好的(因为我们使用MyBatis可不想去知道它初始化到底要做些啥事之类的)。因此使用这个方法是最优雅的解决方案。Spring在1.0就支持了这个接口,优秀~
总结
Spring提供了非常多的方式来向容器内注册Bean,从而来满足各式各样的需求。每种方式都有他独特的使用场景。比如@Bean是最长使用的,@Import导入Bean在SpringBoot的自动装配中得到了大量的使用。
一个成熟的框架很忌讳提供封闭的、不全的功能。而Spring在“开闭原则”上显然无疑是做得非常优秀的,值得深入学习