1. 程式人生 > 實用技巧 >Spring原始碼之FactoryBean的實現

Spring原始碼之FactoryBean的實現

https://zhuanlan.zhihu.com/p/97005407
https://blog.csdn.net/qq_35634181/article/details/104507465

總結

  1. FactoryBean的物件會先在createWebServer時,建立BeanWrapper,並放到factoryBeanInstanceCache快取中
  2. 在預例項化時,走FactoryBean邏輯,呼叫getBean去執行屬性注入、初始化過程(此時物件例項化直接從factoryBeanInstanceCache快取中取)
  3. 完成FactoryBean的實現類初始化
  4. 呼叫實現類的getObject方法,從而對工廠中類進行功能增強

FactoryBean(實現類)的初始化

初始化入口依然是AbstractApplicationContext#finishBeanFactoryInitialization() ,走到DefaultListableBeanFactory類preInstantiateSingletons方法時,和普通bean邏輯不同,執行以下程式碼:

@Override
public void preInstantiateSingletons() throws BeansException {


	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
		    //FactoryBean的初始化執行入口
			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 {
			    //普通bean的執行入口
				getBean(beanName);
			}
		}
	}
}	

呼叫Object bean = getBean(FACTORY_BEAN_PREFIX + beanName),後面基本和普通bean的初始化一致

其中不同有:instanceWrapper不為null,是createWebServer時放入factoryBeanInstanceCache中的

if (mbd.isSingleton()) {
	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}

將FactoryBean實現類放入快取呼叫鏈為:

SpringApplication#run() --> SpringApplication#refreshContext() --> SpringApplication#refresh() -->ServletWebServerApplicationContext#refresh() --> AbstractApplicationContext#refresh() --> AbstractApplicationContext#onRefresh() --> ServletWebServerApplicationContext#createWebServer() --> ServletWebServerApplicationContext#getWebServerFactory() --> DefaultListableBeanFactory#getBeanNamesForType() --> DefaultListableBeanFactory#doGetBeanNamesForType() --> AbstractBeanFactory#isTypeMatch() --> AbstractAutowireCapableBeanFactory#getTypeForFactoryBean() --> AbstractAutowireCapableBeanFactory#getSingletonFactoryBeanForTypeCheck()

mbd為:

// Generics potentially only match on the target class, not on the proxy...
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

bw為:

Object instance;
try {
	// Mark this bean as currently in creation, even if just partially.
	beforeSingletonCreation(beanName);
	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
	instance = resolveBeforeInstantiation(beanName, mbd);
	if (instance == null) {
		bw = createBeanInstance(beanName, mbd, null);
		instance = bw.getWrappedInstance();
	}
}
catch (BeanCreationException ex) {
	......
}
finally {
	// Finished partial creation of this bean.
	afterSingletonCreation(beanName);
}

FactoryBean為:

FactoryBean<?> fb = getFactoryBean(beanName, instance);
if (bw != null) {
	this.factoryBeanInstanceCache.put(beanName, bw);
}

獲取FactoryBean實現類(非工廠)的過程

如(此時beanName前面沒有&):

Object factoryBeanTest = context.getBean("factoryBeanTest");

會先在AbstractBeanFactory#doGetBean()中執行:

protected <T> T doGetBean(
		String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
		throws BeansException {


	// Eagerly check singleton cache for manually registered singletons.
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		......
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
}

執行getObjectForBeanInstance方法:

protected Object getObjectForBeanInstance(
		Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    ......
    
	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;
}

呼叫getObjectFromFactoryBean,再呼叫doGetObjectFromFactoryBean方法:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	if (factory.isSingleton() && containsSingleton(beanName)) {
		synchronized (getSingletonMutex()) {
		    //object為null
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
				object = doGetObjectFromFactoryBean(factory, beanName);
				
				......
			}
		}
	}
}	

最後呼叫實際FactoryBean實現類的getObject方法,完成工廠類的自定義功能增強

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
	Object object;
	try {
		if (System.getSecurityManager() != null) {
			......
		}
		else {
		    //去執行實際實現類的getObject方法
			object = factory.getObject();
		}
	}

	return object;
}

通過FactoryBean.getObject方式

如:

FactoryBean bean = (FactoryBean)context.getBean("&factoryBeanTest");
CustomTask customTask = (CustomTask)bean.getObject();

會通過AbstractBeanFactory#doGetBean()直接返回bean

protected <T> T doGetBean(
		String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
		throws BeansException {

	// Eagerly check singleton cache for manually registered singletons.
	//此時一級快取singletonObjects中有資料
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		......
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

呼叫getObjectForBeanInstance,返回beanInstance

protected Object getObjectForBeanInstance(
		Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

	// Don't let calling code try to dereference the factory if the bean isn't a factory.
	//此時為true
	if (BeanFactoryUtils.isFactoryDereference(name)) {
		......
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		return beanInstance;
	}
}

其後便是呼叫FactoryBean實現類的getObject方法,完成工廠類的自定義功能增強

FactoryBean實現示例:

@Component
public class FactoryBeanTest implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        //一些自定義功能
        ......
        return new CustomTask();
    }

    @Override
    public Class<?> getObjectType() {
        return CustomTask.class;
    }
}

springboot中呼叫例子:

@RestController
public class TestController {

    @Autowired
    private AnnotationConfigServletWebServerApplicationContext context;

    @RequestMapping("/test")
    public String test() throws Exception {

        Object factoryBeanTest = context.getBean("factoryBeanTest");
        System.out.println(factoryBeanTest.toString());

        FactoryBean bean = (FactoryBean)context.getBean("&factoryBeanTest");
        CustomTask customTask = (CustomTask)bean.getObject();
        customTask.execute();
        return bean.getObject().toString();
    }
}