FactoryBean是一种特殊的Bean,作用就是创建我们需要的Bean对象,如果对象的创建过程比较复杂,或者要为接口创建动态代理对象等,都可以用FactoryBean来实现
FactoryBean是一种典型的工厂方法模式的运用,在整合框架上面用的比较多,比如整合Mybatis中的MapperFactoryBean
demo
@Component
public class FactoryBeanDemo implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
下面进入源码
ApplicationContext调用refresh方法,倒数第二步,加载bean对象
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// 加载bean对象
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// ...
}
finally {
// ...
}
}
}
最后执行到DefaultListableBeanFactory.preInstantiateSingletons方法
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
// ...
// 把解析到的beanNames一个一个的拿出来遍历
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是不是工厂bean
if (isFactoryBean(beanName)) {
// 获取工厂bean,& + 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());
}
// 只有实现了SmartFactoryBean 并且重写了isEagerInit方法,才会加载真正 的bean,调用getObject方法
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
// 不是FactoryBean走这里
else {
getBean(beanName);
}
}
}
// ...
}
判断是不是FactoryBean
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);
// 先去单例池中找,能找到就直接返回是不是实现了FactoryBean接口
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
// No singleton instance found -> check bean definition.
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
// 单例池找不到,直接通过BeanDefinition判断是不是FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
从前面DefaultListableBeanFactory.preInstantiateSingletons方法中可以看出,工厂bean调用getBean方法传的是 & + beanName ,在我这个demo里是:&factoryBeanDemo
再来看看getBean方法,最终会调到doGetBean方法
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 把&factoryBeanDemo 又转换成factoryBeanDemo,以factoryBeanDemo把对象加载到单例池中
String beanName = transformedBeanName(name);
Object beanInstance;
// 从单例池拿对象,第一次肯定拿不到
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 第一次不会走这里
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// ...
try {
// ...
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建实例,和正常创建实例一样,beanName = factoryBeanDemo
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 获取真正的对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// ...
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
返回真正对象的方法
// 本例中name 传入&factoryBeanDemo, beanName传入factoryBeanDemo
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 这个判断就是判断name是不是&开头,这里为true,直接返回传入的FactoryBeanDemo对象
// 所以ApplicationContext调用refresh方法时触发的对象加载,并不会调用FactoryBean的getObject方法
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
可以看出,ApplicationContext调用refresh方法时触发的对象加载,传入& + beanName,然后进到方法后,又会截取掉&,执行的流程和普通getBean流程一样,最后把beanName对应的FacotyBean对象放入单例池中,本例中就是singletonObjects.put(“factoryBeanDemo” :FactoryBeanDemo对象)
到此ApplicationContext.refresh创建工厂对象的过程就走完了
可以看到,到目前为止还没有调用FactoryBean.getObject方法,那我们怎么拿到getObject返回的对象呢?
答案是:再次调用getBean方法并且不加"&"前缀,如本例中调用getBean(“factoryBeanDemo”)
回到doGetBean方法
// name = factoryBeanDemo
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// 这次从单例池能拿到对象,不过是FactoryBean对象
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 这里真正通过调用FactoryBean.getObject获取需要的对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// ...
}
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 不是以&开头,不会走这个if
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
//
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 从factoryBeanObjectCache取对象,现在还取不到
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 走这里获取FactoryBean.getObject的对象
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
// 是单例,加锁创建
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 这个object已经是调用FactoryBean.getObject获得的对象
object = doGetObjectFromFactoryBean(factory, beanName);
// 判断缓存里是否有,感觉这个判断是不是放在doGetObjectFromFactoryBean方法前更好?
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
// 执行beanPostProcessor的后置处理方法
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
// 存入缓存中,下次就能直接拿到了
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 不是单例,每次都重新创建一下
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 这里调用factory.getObject()获得真正需要的对象
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
总结一下流程:
第一次ApplicationContext.refresh创建FactoryBean对象
- 判断bean是不是FactoryBean
- 如果是FactoryBean,调用getBean("&" + beanName)加载单例bean
- doGetBean方法先把beanName截去"&",然后执行正常加载bean的过程,最后把FactoryBean放入单例池,key是截去"&"的beanName
- 不会调用FactoryBean的getObject方法,而是直接返回FactoryBean对象
第二次getBean(beanName)
- 去单例池拿FactoryBean对象
- 拿到对象,先去factoryBeanObjectCache缓存里看是否有FactoryBean.getObject方法创建的对象
- 没有就调用FactoryBean.getObject方法创建一个对象
- 调用beanPostProcessor的后置处理方法,应该主要是为了看看需不需要生成动态代理对象
- 返回真正的对象
注意:可以看出通过FactoryBean.getObject获得的对象没有经历完整的Bean创建流程,只是会调用beanPostProcessor的后置处理方法,前置处理等方法都不会调用,这一点需要留意