开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
前言
在Spring知识点中,我们最常听见的就是BeanFactory与FactoryBean这两个词,对Spring熟悉的小伙伴对它们俩肯定是熟捻于心,但是对于没有使用过FactoryBean的新手来说,可能连它是用来干嘛的估计都不知道;今天我们就用这篇文章来简单了解一下FactoryBean;
源码分析
我们先来看看FactoryBean长什么样:
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
原来它是一个接口,里面需要实现两个方法,一个返回T类型对象,一个返回Class类型;我们再去看看它是如何被使用的;下面给小伙伴们找了一个很显著的例子,我们可以看一下MybatisSqlSessionFactoryBean:
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
this.afterPropertiesSet();
}
// 返回sqlSessionFactory
return this.sqlSessionFactory;
}
// 返回sqlSessionFactory的类型
public Class<? extends SqlSessionFactory> getObjectType() {
return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
}
}
SqlSessionFactoryBean在mybatis中的主要作用就是通过getObject()获取sqlSessionFactory,我们在Spring中通过@Autowired拿到的sqlSessionFactory就是从这里来的;其他的使用案例还有TransactionProxyFactoryBean:
public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements BeanFactoryAware {
}
主要代码还是在父类AbstractSingletonProxyFactoryBean中:
public Object getObject() {
if (this.proxy == null) {
throw new FactoryBeanNotInitializedException();
} else {
return this.proxy;
}
}
@Nullable
public Class<?> getObjectType() {
if (this.proxy != null) {
return this.proxy.getClass();
} else if (this.proxyInterfaces != null && this.proxyInterfaces.length == 1) {
return this.proxyInterfaces[0];
} else if (this.target instanceof TargetSource) {
return ((TargetSource)this.target).getTargetClass();
} else {
return this.target != null ? this.target.getClass() : null;
}
}
父类中getObject()方法返回的就是代理对象;
从上面两个使用案例中可以发现,FactoryBean就是用来创建Bean对象的,SqlSessionFactoryBean创建的是SqlSessionFactory;TransactionProxyFactoryBean创建的是被代理后的目标对象;
自己实践
为了证实我们自己的想法,我们来自己写一个小案例测试一下:
// 先准备一个实体类
@Data
public class User{
private String name;
private int age;
}
@Component
public class UserFactoryBean implements FactoryBean<User>,InitializingBean{
private User user;
public void afterPropertiesSet() {
user = new User();
user.setName("zouwei");
user.setAge(26);
}
public User getObject() {
return this.user;
}
public Class<?> getObjectType() {
return User.class;
}
}
完成上面两个类的编写后,我们就可以在Spring项目中使用User对象了,我们可以通过@Autowired的方式来获取User对象:
@Autowired
private User user;
虽然我们没有明确把任何User对象交给Spring来管理,但是Spring却可以从UserFactoryBean中拿到它提供的User对象,并且将UserFactoryBean与User对象一起管理起来;
从上面这个示例中,我们可以更加明确FactoryBean与BeanFactory的区别,其实FactoryBean也是一种动态创建Bean的方式,它是通过getObject()方法来动态创建Bean的,BeanFactory只是一个Bean工厂,专门用来管理Bean的,它们俩是完全不同的两个东西;