• 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; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里我也把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;
    	}
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    实例化分析

    确认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);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    启动项目之后的打印内容如下,也就是我这个项目中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);
    					}
    				}
    			}
    		}
    
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    启动打印如下,确实在执行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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    然后就发现再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;
    				}
    			}
    		}
    		//.......省略部分代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    再倒回去,查看到了ConstructorResolver的resolveAutowiredArgument方法中的return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter),这里创建的DependencyDescriptor对象。

    在这里插入图片描述

    DependencyDescriptor

    对象创建时eager默认为true。

    public DependencyDescriptor(MethodParameter methodParameter, boolean required) {
    		this(methodParameter, required, true);
    	}
    
    • 1
    • 2
    • 3

    梳理

    当BeanPostProcessor的实现类被实例化时,会遍历当前工厂中的所有BeanDefinition。如果某个BeanPostProcessor的DependencyDescriptor对象的eager属性为true,表示该Bean的依赖关系是急切加载的。在这种情况下,Spring会提前实例化对应的FactoryBean。所以即使ValidateFactoryBean什么也没干,就相当于是一个普通的单例Bean,只要他是FactoryBean类型也是会提前实例化的。

  • 相关阅读:
    大数据与云计算实验一
    最近5年133个Java面试问题列表
    Codeforces Round #816 (Div. 2) A - D
    Vuex、localStorage和sessionStorage:如何选择合适的数据存储方式?
    谁懂,java后端面试多次惨败并发的苦!幸好有阿里首发并发编程学习文档,系统全面还便于上手!
    C++ Reference: Standard C++ Library reference: C Library: cstring: memcmp
    Flutter中屏幕尺寸设置
    C/C++ 如何调用Lua脚本,C/C++与 Lua的交互
    【入门-07】GPIO
    python的正则表达中的re库一些常用的方法
  • 原文地址:https://blog.csdn.net/Tanganling/article/details/133991637