BeanFactory和FactoryBean在spring中都被定义为接口
1.BeanFactory接口
容器的抽象,定义了管理和获取bean对象的方法,如下图所示
2.FactoryBean
官方文档
类似一个Bean生成工具,方法定义如下
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
实现了FactoryBean的类,spring会调用其getObject、getObjectType创建bean,可以在getObject方法自定义Bean的创建过程
如果想自定义bean的创建过程,并在创建完成后将bean交还由spring管理,则可实现FactoryBean接口
如mybatis-spring就是在getObject方法里对dao接口进行动态代理对象的创建,交由spring管理时将bean对应的BeanDefinition信息中的beanClass改为实现了FactoryBean的class。
public class MapperFactoryBean<T> implements FactoryBean<T> {
private Class<T> t;
private SqlSession sqlSession;
// 其它代码省略
public MapperFactoryBean(Class<T> t) {
this.t = t;
}
@Override
public T getObject() throws Exception {
// 创建代理对象
return MapperProxyUtil.getProxy(t, sqlSession);
}
@Override
public Class<?> getObjectType() {
return t;
}
}
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
public ClassPathMapperScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}
@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 获取指定包下的 BeanDefinition
Set<BeanDefinitionHolder> hodlers = super.doScan(basePackages);
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : hodlers) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
String beanClassName = definition.getBeanClassName();
// 修改bean class为MapperFactoryBean,并将原bean作为构造参数传入
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // 构造函数参数
definition.setBeanClass(MapperFactoryBean.class); // factory bean
definition.getPropertyValues().add("proxyTargetName", beanClassName); // 属性注入
// 根据类型自动注入 - 对MapperFactoryBean的一些属性的set方法进行自动调用,以注入spring容器存在的引用
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
return hodlers;
}
}