Spring FactoryBean浅析
众所周知,Spring容器管理着其内部的Bean,在这些Bean中可能存在着一类特殊的Bean,这一类Bean就是FactoryBean。FactoryBean与其它的Bean不一样的地方在于它能生产Bean。另外,从容器中获取它和它产生的Bean的方式有些特殊。
源码解析
FactoryBean
Spring提供了一个顶级接口FactoryBean用于描述一个FactoryBean应该具备的功能,定义如下
public interface FactoryBean {
// 该Factory生产的Bean实例
@Nullable
T getObject() throws Exception;
// 该Factory生产的Bean class
@Nullable
Class> getObjectType();
// 该Factory生产的Bean是否为单例
default boolean isSingleton() {
return true;
}
该接口提供的方法并不多,也就是说FactoryBean基本的特性只有这三个。
AbstractFactoryBean
Spring提供了一个简单的实现了FactoryBean接口的抽象类,可以基于该抽象类定义我们自己的FactoryBean。
public abstract class AbstractFactoryBean
implements FactoryBean, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
//标识生产的Bean是否为单例
private boolean singleton = true;
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@Nullable
private BeanFactory beanFactory;
// 单例模式下,单例是否已经初始化
private boolean initialized = false;
// 单例模式下持有的单例
@Nullable
private T singletonInstance;
// 在单例模式下,如果需要对外提供Bean,但是单例还未初始化时可以提前该实例,不过对该实例的调用依然会委托给单例,只不过是暂时缓解罢了
@Nullable
private T earlySingletonInstance;
/**
* Set if a singleton should be created, or a new object on each request
* otherwise. Default is {@code true} (a singleton).
*/
public void setSingleton(boolean singleton) {
this.singleton = singleton;
}
@Override
public boolean isSingleton() {
return this.singleton;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public void setBeanFactory(@Nullable BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
/**
* Return the BeanFactory that this bean runs in.
*/
@Nullable
protected BeanFactory getBeanFactory() {
return this.beanFactory;
}
// 返回一个类型转换器,给子类用的
protected TypeConverter getBeanTypeConverter() {
BeanFactory beanFactory = getBeanFactory();
if (beanFactory instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) beanFactory).getTypeConverter();
}
else {
return new SimpleTypeConverter();
}
}
/**
* 必要时提前创建单例
*/
@Override
public void afterPropertiesSet() throws Exception {
if (isSingleton()) {
this.initialized = true;
this.singletonInstance = createInstance();
this.earlySingletonInstance = null;
}
}
// 这个方法用于给Spring提供自己生产的Bean
// 如果是单例模式 单例已经初始化则返回单例,否则返回earlySingletonInstance暂时应付
@Override
public final T getObject() throws Exception {
if (isSingleton()) {
return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
}
else {
return createInstance();
}
}
// 返回单例未初始化时的替代品,注意如果返回的Bean的Class并未实现任何接口,那这步就直接报错了
@SuppressWarnings("unchecked")
private T getEarlySingletonInstance() throws Exception {
Class>[] ifcs = getEarlySingletonInterfaces();
if (ifcs == null) {
throw new FactoryBeanNotInitializedException(
getClass().getName() + " does not support circular references");
}
if (this.earlySingletonInstance == null) {
this.earlySingletonInstance = (T) Proxy.newProxyInstance(
this.beanClassLoader, ifcs, new EarlySingletonInvocationHandler());
}
return this.earlySingletonInstance;
}
// 返回单例
@Nullable
private T getSingletonInstance() throws IllegalStateException {
Assert.state(this.initialized, "Singleton instance not initialized yet");
return this.singletonInstance;
}
// 单例模式下提供销毁功能,具体如何销毁交由子类实现
@Override
public void destroy() throws Exception {
if (isSingleton()) {
destroyInstance(this.singletonInstance);
}
}
// 返回生产的Bean的Class
@Override
@Nullable
public abstract Class> getObjectType();
// 如何创建单例交给子类实现
protected abstract T createInstance() throws Exception;
// 获取Bean的Class对象实现的接口数组,用于创建代理,子类可覆盖
@Nullable
protected Class>[] getEarlySingletonInterfaces() {
Class> type = getObjectType();
return (type != null && type.isInterface() ? new Class>[] {type} : null);
}
// 单例销毁时调用的销毁方法,子类可重写
protected void destroyInstance(@Nullable T instance) throws Exception {
}
// 单例模式下获取Bean时如果单例尚未初始化,通过该Handler返回代理,暂时应付Spring,可为单例的实例化拖延下时间
private class EarlySingletonInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (ReflectionUtils.isEqualsMethod(method)) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (ReflectionUtils.isHashCodeMethod(method)) {
// Use hashCode of reference proxy.
return System.identityHashCode(proxy);
}
else if (!initialized && ReflectionUtils.isToStringMethod(method)) {
return "Early singleton proxy for interfaces " +
ObjectUtils.nullSafeToString(getEarlySingletonInterfaces());
}
try {
return method.invoke(getSingletonInstance(), args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}
接来下看一些有意思的AbstractFactoryBean的实现类
AbstractServiceLoaderBasedFactoryBean
该类通过ServiceLoader实例化Bean,可用于SPI相关应用
public abstract class AbstractServiceLoaderBasedFactoryBean extends AbstractFactoryBean
接下来看看AbstractServiceLoaderBasedFactoryBean的相关实现类
ServiceLoaderFactoryBean
public class ServiceLoaderFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {
@Override
protected Object getObjectToExpose(ServiceLoader> serviceLoader) {
return serviceLoader;
}
@Override
public Class> getObjectType() {
return ServiceLoader.class;
}
}
可以清晰的看到该FactoryBean产生的就是ServiceLoader实例,而通过该ServiceLoader实例我们可以获取SPI的实现类。
ServiceListFactoryBean
public class ServiceListFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {
@Override
protected Object getObjectToExpose(ServiceLoader> serviceLoader) {
List
该FactoryBean产生的Bean是一个装载着SPI实现类实例的List。
ServiceFactoryBean
public class ServiceFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {
@Override
protected Object getObjectToExpose(ServiceLoader> serviceLoader) {
Iterator> it = serviceLoader.iterator();
if (!it.hasNext()) {
throw new IllegalStateException(
"ServiceLoader could not find service for type [" + getServiceType() + "]");
}
return it.next();
}
@Override
@Nullable
public Class> getObjectType() {
return getServiceType();
}
}
该FactoryBean产生的Bean是发现的第一个SPI实现类实例。
使用FactoryBean
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Service
public class StudentFactoryBean extends AbstractFactoryBean {
@Override
public Class> getObjectType() {
return Student.class;
}
@Override
protected Student createInstance() throws Exception {
Student student = new Student();
student.setName("david");
student.setAge(20);
return student;
}
}
将上面的StudentFactoryBean使用注解的方式注册到Spring容器中
运行如下语句
System.out.println(applicationContext.getBean("studentFactoryBean"));
System.out.println(applicationContext.getBean("&studentFactoryBean"));
输出
Student{name='david', age=20}
com.alibaba.my.StudentFactoryBean@35ef1869
可以看到如果我们通过FactoryBean默认的beanName从Spring容器中获取bean,获取到的并不是FactoryBean本身,而是由它产生的Bean(Student),要想获取FactoryBean本身,需要使用&+beanName
总结
本文介绍了Spring中FactoryBean的作用和使用方法,同时介绍了spring-beans中提供的与SPI相关的几个FactoryBean。最后介绍了FactoryBean的使用方法,需要注意的是如何正确获取FactoryBean本身和FactoryBean产生的Bean。