Spring实例化源码解析之FactoryBean(十一)

本来这一章是需要讲解单例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;
	}
	
}

实例化分析

确认FactoryBean加载位置

为了确认在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。

Spring实例化源码解析之FactoryBean(十一)_第1张图片

然后在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

Spring实例化源码解析之FactoryBean(十一)_第2张图片

找到实例化的位置

既然需要实例化,必定会从单例池中去获取,没有这个bean的缓存才会去创建(这句话涉及到单例bean的实例化,将在下一章进行讲解)。所以在AbstractBeanFactory的doGetBean方法中加入条件断点,来逆向的去推什么时候触发的FactoryBean的实例化。

Spring实例化源码解析之FactoryBean(十一)_第3张图片

借助IDEA查看Threads&Variables,可以看到AbstractBeanFactory的getTypeForFactoryBean方法在执行doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);也就是在这里对我们自定义的FactoryBean进行实例化的。

Spring实例化源码解析之FactoryBean(十一)_第4张图片

源码我展示在下面,由于我们默认就是单例的所以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()

Spring实例化源码解析之FactoryBean(十一)_第5张图片

所以传递的值与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对象。

Spring实例化源码解析之FactoryBean(十一)_第6张图片

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类型也是会提前实例化的。

你可能感兴趣的:(Spring专题,spring,java,后端,spring,cloud,spring,boot)