当前位置: 首页 > news >正文

Spring源码分析の构造方法推断

文章目录

  • 前言
  • 一、createBeanInstance
    • 1.1、determineConstructorsFromBeanPostProcessors
    • 1.2、instantiateBean
    • 1.3、autowireConstructor


前言

  在Spring中,如果某个bean只有一个无参的构造方法,那么就会根据该构造方法进行实例化:
在这里插入图片描述在这里插入图片描述  但是如果存在多个呢?
在这里插入图片描述  以及手动使用@AutoWired注解,乃至更复杂的情况?
在这里插入图片描述  这里就涉及到Spring对于构造方法的推断。构造方法的推断,是属于bean生命周期中的实例化阶段

一、createBeanInstance

  createBeanInstance是对于bean进行实例化的方法:

  • 参数一:将要实例化的bean的名称。
  • 参数二:将要实例化的bean的定义。
  • 参数三:getBean方法传入的参数。

  其中args参数,可以理解为指定Spring使用何种构造方法:
在这里插入图片描述这样写默认使用的会是无参构造,为什么等会会说明

  而在getBean方法中指定了这个参数,Spring会按照指定的参数去选择构造方法。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
	}
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	//可以在bean定义中指定需要创建哪一个bean
	//例: beanDefinition.setInstanceSupplier(()->new OrderService());
	//创建出的就是OrderService的实例
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}
	//如果bean定义中包含工厂方法名称,则通过工厂方法来实例化bean
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
	//-----------------和构造方法有关的逻辑--------------------
	//resolved用于标记构造函数是否已解析
	//autowireNecessary标记是否需要自动装配构造函数。
	boolean resolved = false;
	boolean autowireNecessary = false;
	// // 如果args为null,则检查构造函数是否已经解析并缓存
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
			//这个属性保存了bean定义中解析出来的构造函数或工厂方法。
			//如果这个属性不为null,说明bean的构造函数(或者工厂方法)已经被解析并准备好。
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				//标记resolved为true,表示构造函数已经解析
				resolved = true;
				//确定是否需要自动装配。
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	//如果构造函数已解析,则根据是否需要自动装配来决定创建bean的方式。
	if (resolved) {
		//如果需要自动装配
		if (autowireNecessary) {
			//1.3、autowireConstructor	进行构造函数自动装配
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			//1.2、instantiateBean 直接使用已解析的构造函数实例化bean。
			return instantiateBean(beanName, mbd);
		}
	}
	//1.1、determineConstructorsFromBeanPostProcessors 构造方法的推论
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	//推断出的构造不为空 或者 bean定义设置成了允许Spring去自己推断构造 或者 bean定义中有构造参数或传入了构造参数
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		//进行自动装配
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	// Preferred constructors for default construction?
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		return autowireConstructor(beanName, mbd, ctors, null);
	}
	//如果没有任何候选构造函数或首选构造函数,则使用默认的无参构造函数实例化bean。
	return instantiateBean(beanName, mbd);
}

  在上面这段代码中,首先会去检查缓存,resolved 表示构造函数是否已解析,而autowireNecessary 表示是否需要自动装配构造函数。那么什么情况下autowireNecessary 会被设置成true?

@Component
public class MyBean {
    private final OtherBean otherBean;
    
    @Autowired
    public MyBean(OtherBean otherBean) {
        this.otherBean = otherBean;
    }
}

  mbd.resolvedConstructorOrFactoryMethod != null表示的是重复创建同一个bean的情况,Spring可以重用已解析的构造函数,避免每次都解析构造函数。

1.1、determineConstructorsFromBeanPostProcessors

  determineConstructorsFromBeanPostProcessors用于构造方法的推论。能走到该方法,说明:

  1. 构造函数之前没有被解析,也就是该bean第一次被创建。
  2. 和传入的args无关,无论是否传递该参数,只要条件1满足,都会进行推断。

在这里插入图片描述AbstractAutoProxyCreator是一个空实现,真正的实现是AutoWired…

@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
        throws BeanCreationException {

    // 1. 检查是否存在查找方法(@Lookup注解的方法),如果是第一次检查该bean的查找方法,则处理查找方法。
    if (!this.lookupMethodsChecked.contains(beanName)) {
        // 如果beanClass是一个候选类
        if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
            try {
                // 从当前beanClass开始遍历所有继承的类
                Class<?> targetClass = beanClass;
                do {
                    // 遍历当前类的所有方法
                    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                        // 如果方法上有@Lookup注解
                        Lookup lookup = method.getAnnotation(Lookup.class);
                        if (lookup != null) {
                            Assert.state(this.beanFactory != null, "No BeanFactory available");

                            // 创建一个LookupOverride对象,用于后续处理
                            LookupOverride override = new LookupOverride(method, lookup.value());
                            try {
                                // 获取bean的定义
                                RootBeanDefinition mbd = (RootBeanDefinition)
                                        this.beanFactory.getMergedBeanDefinition(beanName);

                                // 添加Override到bean的methodOverrides中
                                mbd.getMethodOverrides().addOverride(override);
                            }
                            catch (NoSuchBeanDefinitionException ex) {
                                throw new BeanCreationException(beanName,
                                        "Cannot apply @Lookup to beans without corresponding bean definition");
                            }
                        }
                    });
                    // 向上遍历父类
                    targetClass = targetClass.getSuperclass();
                }
                while (targetClass != null && targetClass != Object.class);
            }
            catch (IllegalStateException ex) {
                throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
            }
        }
        // 将该bean名称标记为已检查过
        this.lookupMethodsChecked.add(beanName);
    }

    // 2. 尝试从缓存中获取该beanClass的构造函数
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
        // 3. 如果缓存中没有,进入同步代码块解析构造函数
        synchronized (this.candidateConstructorsCache) {
            candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            if (candidateConstructors == null) {
                Constructor<?>[] rawCandidates;
                try {
                    // 获取bean类的所有构造函数(包括有参和无参的)
                    rawCandidates = beanClass.getDeclaredConstructors();
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName,
                            "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                            "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }

                // 存储候选构造函数
                List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
                // 存储需要的构造函数
                Constructor<?> requiredConstructor = null;
                // 存储默认构造函数
                Constructor<?> defaultConstructor = null;
                //和Kotlin有关,可以忽略
                Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
                int nonSyntheticConstructors = 0;

                // 遍历所有的构造函数
                for (Constructor<?> candidate : rawCandidates) {
                    if (!candidate.isSynthetic()) {
                    		//一般情况下的构造函数,nonSyntheticConstructors计数+1
                        nonSyntheticConstructors++;  
                    }
                    else if (primaryConstructor != null) {
                        continue; //和Kotlin有关,可以忽略
                    }

                    // 查找构造函数上是否存在@Autowired注解
                    MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
                    // 如果在当前类找不到,继续查找父类构造函数
                    if (ann == null) {
                        Class<?> userClass = ClassUtils.getUserClass(beanClass);
                        if (userClass != beanClass) {
                            try {
                                // 如果类继承自其他类,查找父类中是否有匹配的构造函数
                                Constructor<?> superCtor =
                                        userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                ann = findAutowiredAnnotation(superCtor);
                            }
                            // 如果父类没有对应的构造函数,继续向下执行
                            catch (NoSuchMethodException ex) {
                                
                            }
                        }
                    }
								
								//如果构造函数上存在@Autowired注解
                    if (ann != null) {
                        // 如果已找到required标记的构造函数,则抛出异常
                        if (requiredConstructor != null) {
                        		//因为一个bean只能有一个required构造函数
                            throw new BeanCreationException(beanName,
                                    "Invalid autowire-marked constructor: " + candidate +
                                    ". Found constructor with 'required' Autowired annotation already: " +
                                    requiredConstructor);
                        }

                        // 判断@Autowired是否标记为required
                        boolean required = determineRequiredStatus(ann);
                        if (required) {
                            if (!candidates.isEmpty()) { // 如果已经有候选构造函数
                             // 抛出异常,因为一个bean不能同时有多个required构造函数
                                throw new BeanCreationException(beanName,
                                        "Invalid autowire-marked constructors: " + candidates +
                                        ". Found constructor with 'required' Autowired annotation: " +
                                        candidate);
                            }
                            // 设置为需要的构造函数
                            requiredConstructor = candidate;
                        }
                        // 将构造函数加入候选列表
                        candidates.add(candidate);
                    }
                    else if (candidate.getParameterCount() == 0) {
                        // 如果是无参构造函数,记录为defaultConstructor
                        defaultConstructor = candidate;
                    }
                }

                // 如果找到autowire标记的构造函数,处理requiredConstructor
                if (!candidates.isEmpty()) {
                		// 如果没有找到required为ture构造函数
                    if (requiredConstructor == null) {
                    		// 如果有默认构造函数
                        if (defaultConstructor != null) {
                        		//将默认构造设置为候选构造函数
                            candidates.add(defaultConstructor);
                        }
                        else if (candidates.size() == 1 && logger.isInfoEnabled()) {
                            logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
                                    "': single autowire-marked constructor flagged as optional - " +
                                    "this constructor is effectively required since there is no " +
                                    "default constructor to fall back to: " + candidates.get(0));
                        }
                    }
                    candidateConstructors = candidates.toArray(new Constructor<?>[0]);
                }
                // 如果只找到一个带参数的构造函数
                else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
                    candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
                }
               //和Kotlin有关,可以忽略
                else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
                        defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
                    candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
                }
               //和Kotlin有关,可以忽略
                else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
                    candidateConstructors = new Constructor<?>[] {primaryConstructor};
                }
                // 如果没有候选构造函数
                else {
                    candidateConstructors = new Constructor<?>[0];
                }

                // 将解析结果缓存起来
                this.candidateConstructorsCache.put(beanClass, candidateConstructors);
            }
        }
    }

    // 返回找到的候选构造函数,如果没有找到,则返回null 走默认无参构造的逻辑
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

  这一块的逻辑非常复杂,这里仅仅用两种常见的情况进行说明:
在这里插入图片描述一个默认的无参构造,一个有参构造

  首先得到OrderService的所有构造方法:
在这里插入图片描述  遍历所有的构造方法:
在这里插入图片描述  找注入点,现在OrderService上没有任何加了@AutoWired的构造方法。
在这里插入图片描述  Class<?> userClass = ClassUtils.getUserClass(beanClass);的逻辑:
在这里插入图片描述  如果当前bean是被cglib代理过的,就去父类中找。
在这里插入图片描述  下一个if也不满足,因为当前构造方法上没有@AutoWired
在这里插入图片描述  第一个遍历到的是无参构造方法,参数的个数为0,所以被标记为默认的构造
在这里插入图片描述  第二个遍历到的是有参构造方法,流程和第一个类似,在执行完这个循环后,defaultConstructor被设置成了无参构造,而nonSyntheticConstructors集合的个数为2:
在这里插入图片描述  下面的条件都不满足,会进入最后的else:
在这里插入图片描述  最终返回null,返回null代表什么,会在instantiateBean里说明:
在这里插入图片描述


  再简单地看下加上了@AutoWired的情况:在这里插入图片描述
  第一次循环的是无参构造,最终会加入defaultConstructor
在这里插入图片描述  第二次循环的是带有@AutoWired注解的有参构造,找到了注入点:
在这里插入图片描述
  @AutoWired注解的required参数默认为true,这里进行了判断,如果有多个加上了@AutoWired注解,并且没有显式指定required属性,或者required都为true的情况下,会报错。
在这里插入图片描述
  然后将当前的构造方法设置成需要的构造方法:
在这里插入图片描述  在放入缓存后,返回的不是null,而是加上了@AutoWired注解的构造:
在这里插入图片描述


在这里插入图片描述设置了多个@AutoWired注解的构造,会出现异常

在这里插入图片描述

简单地小结一下determineConstructorsFromBeanPostProcessors方法:

如果当前没有加@AutoWired注解:

  • 多个有参构造,并且有一个无参构造,返回null
  • 有多个有参构造,没有默认的无参构造,报错
  • 只有一个无参构造,返回null
  • 只有一个有参构造,返回该有参构造

如果当前加@AutoWired注解:

  • 有多个require为true的,报错
  • 只有一个require为true的,返回该构造
  • 没有require为true的,返回所有构造,包括无参

1.2、instantiateBean

  instantiateBean的底层最终是采用默认的无参构造去创建对象:
在这里插入图片描述

1.3、autowireConstructor

  autowireConstructor是处理determineConstructorsFromBeanPostProcessors方法的返回不为null的逻辑,包括当前没有加@AutoWired注解,只有一个有参构造的情况,以及如果当前加@AutoWired注解,只有一个require为true的、没有require为true的情况。

  • 参数一:当前bean的名称。
  • 参数二:当前bean的定义。
  • 参数三:推断出的构造方法。
  • 参数四:显式的构造函数参数。

  这段代码最复杂的地方在于歧义处理,即:如果存在构造函数的类型匹配度相同的多个候选项,则会处理歧义情况,有机会单独开一篇说明。

相关文章:

  • Android SystemUI深度定制实战:下拉状态栏集成响铃功能开关全解析
  • 设备健康管理系统在制造业的深度应用探索
  • 无人机 CAAC 执照考取全攻略
  • 第8天:面向对象编程入门 - 类与对象
  • 面试问题——如何解决移动端1px 边框问题?
  • 同步锁:同步实现的几种方式
  • NFC拉起微信小程序申请URL scheme 汇总
  • 一文掌握ADSL拨号代理的搭建方法,及详细使用
  • 如何证明有限域的大小都是2的幂次
  • 千峰React:Hooks(上)
  • 利用 Windows Terminal 和 SSH Config 简化 Linux 服务器管理
  • postgresql postgis扩展相关
  • VSCode 使用import导入js/vue等时添加智能提示,并可跳转到定义
  • 改进YOLOv8模型的空间注意力机制研究:RFAConv的贡献与实现
  • PostgreSQL的备份方式
  • SQL注入(order by、limit),seacmsv9联合注入数据
  • ROS2中的图形化显示---visualization_msgs
  • 【缓冲区】数据库备份的衍生问题,缓冲区在哪里?JVMor操作系统?(二)
  • 大模型应用案例 | 大模型+金融运维,擎创携手某证券创新运维能力新范式
  • 力扣-动态规划-70 爬楼梯
  • 王毅谈中拉论坛第四届部长级会议重要共识
  • 著名连环画家庞邦本逝世
  • 沙县小吃中东首店在沙特首都利雅得开业,首天营业额5万元
  • 国内首例侵入式脑机接口系统前瞻性临床试验:受试者已能用意念玩游戏
  • 构筑高地共伴成长,第六届上海创新创业青年50人论坛在沪举行
  • 肖峰读《从塞北到西域》︱拉铁摩尔的骆驼