本来这一章是需要讲解单例bean的实例化流程的,但是突然发现自定义的FactoryBean其实在registerBeanPostProcessors期间就被实例化了,然后就打算一探究竟。
关于FactoryBean的作用和用法在手动实现mybatis代理接口对象这篇文章已经有了讲解,本章主要分析FactoryBean的实例化流程。
创建一个FactoryBean,用于验证,由于手动实现mybatis代理接口对象这篇文章,所以我有两个自定义的FactoryBean,只是ValidateFactoryBean就仅仅是一个单例的Bean。
package com.qhyu.cloud.mybatis.config;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
/**
* All rights Reserved, Designed By https://umd.edu/
* Title:ValidateFactoryBean
* Package:com.qhyu.cloud.mybatis.config
* Copyright © 2023 umd.edu. All rights reserved.
* Company:The University of Maryland
*
* @author candidate
* @date 2023年 10月12日 15:49
*/
@Component
public class ValidateFactoryBean<T> implements FactoryBean<T> {
@Override
public T getObject() throws Exception {
return null;
}
@Override
public Class<?> getObjectType() {
return null;
}
}
在这里我也把MapperFactoryBean给展示出来
package com.qhyu.cloud.mybatis.config;
import com.qhyu.cloud.mybatis.handler.MethodArgsHandler;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
import java.lang.reflect.Proxy;
@Component
public class MapperFactoryBean<T> implements FactoryBean<T> {
public MapperFactoryBean() {
}
private Class<T> target;
public MapperFactoryBean(Class<T> target) {
this.target = target;
}
@Override
@SuppressWarnings({"unchecked","rawtypes"})
public T getObject() throws Exception {
// 在这里产生代理对象,具体实现看手动实现mybatis代理接口对象这篇文章
return (T) Proxy.newProxyInstance(target.getClassLoader(), new Class[]{getObjectType()}, new MethodArgsHandler());
}
/** 默认返回单例就行 */
@Override
public boolean isSingleton() {
return true;
}
@Override
public Class<T> getObjectType() {
// 直接返回target的类型
return target;
}
}
为了确认在AbstractApplicationContext中的refresh方法里面的registerBeanPostProcessors(beanFactory)调用之前是没有实例化FactoryBean的,我在源码中加了一个preRegisterBeanPostProcessors方法
/**
* Title: 注册BeanPostProcessor之前容器中有哪些bean了
* @author candidate
* @date 2023/10/12 15:12
* @since 2023/10/12
* @param beanFactory ConfigurableListableBeanFactory
*/
private void preRegisterBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
for (String singletonName : beanFactory.getSingletonNames()) {
System.out.println("preRegisterBeanPostProcessors:"+ singletonName);
}
}
启动项目之后的打印内容如下,也就是我这个项目中registerBeanPostProcessors(beanFactory)之前注入到容器中的bean。
然后在registerBeanPostProcessors(beanFactory)执行之后也按照相同的逻辑来查看FactoryBean是否会被实例化。新增一个afterRegisterBeanPostProcessors方法。
/**
* Title: 验证我的猜想是否正确,我要知道FactoryBean的实例化时机
* @author candidate
* @date 2023/10/11 15:08
* @since 2023/10/11
* @param beanFactory ConfigurableListableBeanFactory
*/
private void afterRegisterBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
String[] singletonNames = beanFactory.getSingletonNames();
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
if(beanFactory.isFactoryBean(beanDefinitionName)){
System.out.println("当前Bean是FactoryBean:"+beanDefinitionName);
for (String singletonName : singletonNames) {
System.out.println("afterRegisterBeanPostProcessors:"+ singletonName);
if (beanDefinitionName.contains(singletonName)){
System.out.println("FactoryBean已初始化完成"+singletonName);
}
}
}
}
}
启动打印如下,确实在执行registerBeanPostProcessors(beanFactory)的时候实例化了我们的FactoryBean
既然需要实例化,必定会从单例池中去获取,没有这个bean的缓存才会去创建(这句话涉及到单例bean的实例化,将在下一章进行讲解)。所以在AbstractBeanFactory的doGetBean方法中加入条件断点,来逆向的去推什么时候触发的FactoryBean的实例化。
借助IDEA查看Threads&Variables,可以看到AbstractBeanFactory的getTypeForFactoryBean方法在执行doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);也就是在这里对我们自定义的FactoryBean进行实例化的。
源码我展示在下面,由于我们默认就是单例的所以mbd.isSingleton()是返回true,然后allowInit就变为了关键,我们需要再基于上述的断点往前倒腾,查看这个值是从哪里来的。
protected ResolvableType getTypeForFactoryBean(String beanName, RootBeanDefinition mbd, boolean allowInit) {
ResolvableType result = getTypeForFactoryBeanFromAttributes(mbd);
if (result != ResolvableType.NONE) {
return result;
}
if (allowInit && mbd.isSingleton()) {
try {
System.out.println("AbstractBeanFactory-CG1719-获取FactoryBean:"+FACTORY_BEAN_PREFIX + beanName);
FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
Class<?> objectType = getTypeForFactoryBean(factoryBean);
return (objectType != null ? ResolvableType.forClass(objectType) : ResolvableType.NONE);
}
catch (BeanCreationException ex) {
if (ex.contains(BeanCurrentlyInCreationException.class)) {
logger.trace(LogMessage.format("Bean currently in creation on FactoryBean type check: %s", ex));
}
else if (mbd.isLazyInit()) {
logger.trace(LogMessage.format("Bean creation exception on lazy FactoryBean type check: %s", ex));
}
else {
logger.debug(LogMessage.format("Bean creation exception on eager FactoryBean type check: %s", ex));
}
onSuppressedException(ex);
}
}
return ResolvableType.NONE;
}
然后就发现再DefaultListableBeanFactory的findAutowireCandidates的方法中传递的是descriptor.isEager()
所以传递的值与DependencyDescriptor这个对象相关。
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
System.out.println("当前BeanName="+beanName+" isEager(是否急切)="+descriptor.isEager()+" 要求得类型="+requiredType.getName());
// 这里传入了true,也就是descriptor的信息里面传入的
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//.......省略部分代码
再倒回去,查看到了ConstructorResolver的resolveAutowiredArgument方法中的return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter),这里创建的DependencyDescriptor对象。
对象创建时eager默认为true。
public DependencyDescriptor(MethodParameter methodParameter, boolean required) {
this(methodParameter, required, true);
}
当BeanPostProcessor的实现类被实例化时,会遍历当前工厂中的所有BeanDefinition。如果某个BeanPostProcessor的DependencyDescriptor对象的eager属性为true,表示该Bean的依赖关系是急切加载的。在这种情况下,Spring会提前实例化对应的FactoryBean。所以即使ValidateFactoryBean什么也没干,就相当于是一个普通的单例Bean,只要他是FactoryBean类型也是会提前实例化的。