Spring 5.x 源码之旅-23getBean详解九之构造方法实例化

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

 

determineConstructorsFromBeanPostProcessors

前面讲了工厂方法的实例化,现在可以讲一般的构造方法实例化了,首先会进行处理器处理,找出合适的构造方法:

    @Nullable
    	protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
    			throws BeansException {
    
    		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
    					Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
    					if (ctors != null) {
    						return ctors;
    					}
    				}
    			}
    		}
    		return null;
    	}

AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors

主要是这个处理器做的事,开始检查Lookup注解,然后处理,添加方法覆盖。主要还是后面的构造函数获取,首先获取缓存,如果没有的话就获取所有的构造函数,然后每个构造函数都进行遍历,获取注解,如果为空的话,判断是不是代理类,是的话就获取父类,也就是我们自己定义的类,再次获取注解。如果注解存在,就看Autowiredrequired属性,如果有多个是true或者有一个是true,其他是false都会报错,因为他没办法知道该用哪个,如果全是false,那是可以的。如果只有一个false,会报一个警告。如果有Autowired注解的,就优先注解的构造方法,如果没有,就只有一个构造方法且有参数的优先,然后是有优先构造方法,跟Kotlin有关,所以基本不会优先,然后剩下的就是默认构造方法了。注意如果有多个有参构造方法其实他也不知道要用哪个,实例化的时候会去找默认构造方法,但是没找到,会报异常。

    @Override
    	@Nullable
    	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
    			throws BeanCreationException {
    
    		// 查找lookup
    		if (!this.lookupMethodsChecked.contains(beanName)) {
    			if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
    				try {
    					Class<?> targetClass = beanClass;
    					do {//遍历当前类以及所有父类,找出Lookup注解的方法进行处理
    						ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    							Lookup lookup = method.getAnnotation(Lookup.class);
    							if (lookup != null) {
    								Assert.state(this.beanFactory != null, "No BeanFactory available");
    								LookupOverride override = new LookupOverride(method, lookup.value());
    								try {
    									RootBeanDefinition mbd = (RootBeanDefinition)
    											this.beanFactory.getMergedBeanDefinition(beanName);
    									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);//遍历父类,直到Object
    
    				}
    				catch (IllegalStateException ex) {
    					throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
    				}
    			}
    			this.lookupMethodsChecked.add(beanName);//已经检查过
    		}
    
    		//先检查一遍缓存
    		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    		if (candidateConstructors == null) {//没找到再同步
    			// Fully synchronized resolution now...
    			synchronized (this.candidateConstructorsCache) {
    				candidateConstructors = this.candidateConstructorsCache.get(beanClass);//再检测一遍,双重检测
    				if (candidateConstructors == null) {
    					Constructor<?>[] rawCandidates;
    					try {
    						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;//默认构造方法
    					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);//优先的构造方法,Kotlin的类才有,一般都是空
    					int nonSyntheticConstructors = 0;
    					for (Constructor<?> candidate : rawCandidates) {
    						if (!candidate.isSynthetic()) {//非合成的方法
    							nonSyntheticConstructors++;
    						}
    						else if (primaryConstructor != null) {
    							continue;
    						}
    						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);//寻找Autowired和value的注解
    						if (ann == null) {
    							Class<?> userClass = ClassUtils.getUserClass(beanClass);
    							if (userClass != beanClass) {//如果是有代理的,找到被代理类
    								try {
    									Constructor<?> superCtor =//获取构造方法
    											userClass.getDeclaredConstructor(candidate.getParameterTypes());
    									ann = findAutowiredAnnotation(superCtor);//继续寻找Autowired和value的注解
    								}
    								catch (NoSuchMethodException ex) {
    									// Simply proceed, no equivalent superclass constructor found...
    								}
    							}
    						}
    						if (ann != null) {
    							if (requiredConstructor != null) {//有两个Autowired注解,冲突了
    								throw new BeanCreationException(beanName,
    										"Invalid autowire-marked constructor: " + candidate +
    										". Found constructor with 'required' Autowired annotation already: " +
    										requiredConstructor);
    							}
    							boolean required = determineRequiredStatus(ann);//是否需要,默认是true
    							if (required) {
    								if (!candidates.isEmpty()) {//如果已经有required=false了,又来了一个required=true的方法就报异常了,这样两个可能就不知道用哪个了
    									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 = candidate;
    						}
    					}
    					if (!candidates.isEmpty()) {//如果候选不为空,基本就是有Autowired注解的,转换成数组直接返回
    						// Add default constructor to list of optional constructors, as fallback.
    						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]};//只有一个函数且有参数
    					}
    					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
    							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
    						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};//有两个非合成方法,有优先方法和默认方法,且不相同
    					}
    					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {//只有一个优先的
    						candidateConstructors = new Constructor<?>[] {primaryConstructor};
    					}
    					else {//大于2个没注解的构造方法就不知道要用什么了,所以就返回null
    						candidateConstructors = new Constructor<?>[0];
    					}
    					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
    				}
    			}
    		}
    		return (candidateConstructors.length > 0 ? candidateConstructors : null);
    	}

总结下就是:

  • 如果有多个Autowiredrequiredtrue,不管有没有默认构造方法,会报异常。
  • 如果只有一个Autowiredrequiredfalse,没有默认构造方法,会报警告。
  • 如果没有Autowired注解,定义了2个及以上有参数的构造方法,没有无参构造方法,就会报错。
  • 其他情况都可以,但是以有Autowired的构造方法优先,然后才是默认构造方法。

如果构造方法存在且是有参数的,那就会调用autowireConstructor进行自动装配,如果不存在基本上无参构造方法了,除非有Kotlin提供优先构造方法。后面来讲自动装配和默认构造方法怎么实例化吧。

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值