前言
在spring中FactoryBean绝对是一种神奇的存在,和BeanFactory经常混淆,而且成为面试过程中经常被问到的问题,其实FactoryBean和BeanFactory很好理解,掌握一定的技巧即可。
初识
FactoryBean翻译过来是工厂Bean,BeanFactory翻译过来是Bean工厂,前者是bean工厂beanFactory中的一个bean,只不过这个bean和一般的bean不一样,它有着自己的特殊之处,特殊在什么地方那,在spring中提供了FactoryBean的接口,
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
FactoryBean接口很简单,就提供了三个方法getObject、getObjectType、isSingleton。就是这三个方法却成为了spring中很多功能的基础,搜索整个spring的源码可以找到很多FactoryBean,除了spring自身提供的以外,在和一些框架进行集成的时候,同样有FactoryBean的影子,比如和mybatis集成的时候的SqlSessionFactoryBean,
用法
这里以springboot的环境为例演示下FactoryBean的用法,有需要源码的可关注公众号【北漂程序员】私聊我。
自定义FactoryBean,仅在getObject方法内自己new了一个Student对象,且返回该对象;重写了toString方法,为了测试用。
package com.example.myDemo.component;
import com.example.myDemo.po.Student;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
@Component
public class MyFactoryBean implements FactoryBean<Student> {
@Override
public Student getObject() throws Exception {
Student student=new Student();
return student;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public String toString() {
return "MyFactoryBean{}";
}
}
下面是Student类,很简单就两个属性且重写了toString方法,
package com.example.myDemo.po;
public class Student {
private String name;
private String code;
public Student(String name, String code) {
this.name = name;
this.code = code;
}
public Student() {
}
@Override
public String toString() {
return "Student{}";
}
}
下面就是测试的方法了,
package com.example.myDemo;
import com.example.myDemo.component.MyFactoryBean;
import com.example.myDemo.po.Student;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.ApplicationContext;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MyDemoApplication {
public static void main(String[] args) {
ApplicationContext ac=SpringApplication.run(MyDemoApplication.class, args);
//获得Student对象
Student stu=(Student) ac.getBean("myFactoryBean");
//获得MyFactoryBean对象
MyFactoryBean myFactoryBean=(MyFactoryBean) ac.getBean("&myFactoryBean");
System.out.println("stu:"+stu);
System.out.println("myFactoryBean:"+myFactoryBean);
}
}
先看下打印结果,
打印结果很奇怪通过“myFactoryBean”获得了Student对象,通过“&myFactoryBean”获得了MyFactoryBean对象。为什么会这样
功能解释
看了上面的输出结果很多小伙伴都很诧异,没错这就是FactoryBean的神奇, 通俗点讲FactoryBean是一个工厂bean,它是一种可以生产bean的bean,通过其getObejct方法生产bean。 当然不论是FactoryBean还是FactoryBean生产的bean都是受spring管理的这点是没有问题的,不然通过getBean方法是拿不到的。
上面讲了那么多到底FactoryBean的用处是什么,前面讲到FactroyBean的作用是生产一个Bean,这里有一个疑问spring就是用来生产bean和管理bean的,为什么还要有FactoryBean,FactoryBean的真正目的是让开发者自己去定义那些复杂的bean并交给spring管理,如果bean中要初始化很多变量,而且要进行许多操作,那么使用spring的自动装配是很难完成的,所以spring的开发者把这些工作交给了我们。一个比较常见的例子是,在mybatis和spring集成的时候便有这样一个FactoryBean,名字叫SqlSessionFactoryBean,这个FactoryBean的目的就是返回一个spring管理的SqlSessionFactory,使用过mybatis的都知道要创建一个sqlSessionFactory需要配置很多属性,所以便有了SqlSessionFactoryBean,下面看下SqlSessionFactoryBean,
看下sqlSessionFactoryBean的getObejct方法
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
this.afterPropertiesSet();
}
return this.sqlSessionFactory;
}
getObejctType方法
public Class<? extends SqlSessionFactory> getObjectType() {
return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
}
isSingleton方法
public boolean isSingleton() {
return true;
}
总结
本篇文章主要带小伙伴了解了FactoryBean这种特殊的Bean,它的作用就是生产Bean。这里有个疑问在使用getBean方法的时候,为什么传入“myFactoryBean”和“&MyFactoryBean”两个值返回值一个是FactoryBean生产的bean,一个是FactorBean那,下篇通过源码来揭秘,揭秘getObjectForBeanInstance方法的那些事,欢迎关注。
原文链接:
http://www.cnblogs.com/teach/p/14951920.html
如果觉得本文对你有帮助,可以转发关注支持一下