1 什么是 FactoryBean接口?
很多同学都知道BeanFactory
接口,这个是大名鼎鼎的Spring中的核心接口,IOC的根本所在。而这个FactoryBean
的作用是用来创建一类bean,它的源代码是这样的:
public interface FactoryBean<T> {
// 获取 ObjectType 的一个对象
T getObject() throws Exception;
// 当前实现类所要创建的对象类型
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
上面这个图可以很简单的去概括这个接口的作用,就是要一个对象,然后给一个对象的逻辑。
1.1 小小的深入一点
对于 FactoryBean
接口,其实还有一个子接口,叫做SmartFactoryBean
public interface SmartFactoryBean<T> extends FactoryBean<T> {
// 最核心的一个方法 --> 如果说这里返回 true 那么则会在 Spring容器初始化的时候就将这个Bean实例化
default boolean isEagerInit() {
return false;
}
}
下面这段代码则是对于SmartFactoryBean
的迫切加载在Spring中的体现:
// 这段代码来自 DefaultListableBeanFactory -> 922 行
public void preInstantiateSingletons() throws BeansException {
// 省略部分代码
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 核心点便是这里了
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
}
1.2 实战一把
对于FactoryBean
的使用其实只分为俩步:
- 实现
FactoryBean
接口 - 将实现类注入Bean工厂
下面这段代码来自Easy ES
的源码,同理也可以在Mybatis
的底层代码中找到类似的设计(对SqlSession的FactoryBean),这样便相当于托管给实现类创建一类Bean的能力
@Component // 注入BeanFactory
public class MapperFactoryBean<T> implements FactoryBean<T> {
private final Class<T> mapperInterface;
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
@Override
@SuppressWarnings("all")
public T getObject() throws Exception {
EsMapperProxy<T> esMapperProxy = new EsMapperProxy<>(mapperInterface);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, esMapperProxy);
}
// 这个便是这个FactoryBean所要创建的类型
@Override
public Class<?> getObjectType() {
return this.mapperInterface;
}
}