Spring 5.x 源码之旅-21getBean详解七

作者简介:大家好,我是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下的验证结果当作最终结果的水货们请闭嘴】

 

DefaultListableBeanFactory的doResolveDependency解析依赖

继续上篇的,如果是我们自己定义的类型的参数,没有懒加载注解的,就会进行解析。
首先看BeanFactiry是否有添加快捷方式,一般没有,除非子类继承扩展,然后看是否有注解方法设置的参数的值,有的话就设置处理。否则的话就判断是否是多个bean的注入,比如参数类型是集合。最后才是获取自动装配类型的对象findAutowireCandidates,如果找到多个的话,会进行优先级来选取,然后进行装配类型对象的创建,这里的创建又是一个getBean的过程,但是也可能是直接获取,一般来说是主要看工厂方法的定义顺序,因为内部可以用了ASM处理,但是如果有重名的,就乱序了,具体为什么不行可以看ConfigurationClassParserretrieveBeanMethodMetadata方法,不过影响也不大,反正都能自动装配好。创建好了再判断类型是否匹配,最后返回。下面我们来分析几个主要的方法,主要的理解了,其他的自己慢慢了解就行。

    	@Nullable
    	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    		//设置注入点,并获得前一个注入点,以便后面可以设置回来
    		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    		try {//解析快捷方式,存在就返回,子类BeanFactiry可以扩展,默认null
    			Object shortcut = descriptor.resolveShortcut(this);
    			if (shortcut != null) {
    				return shortcut;
    			}
    
    			Class<?> type = descriptor.getDependencyType();
    			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);//获取注解可能的值
    			if (value != null) {
    				if (value instanceof String) {
    					String strVal = resolveEmbeddedValue((String) value);
    					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
    							getMergedBeanDefinition(beanName) : null);
    					value = evaluateBeanDefinitionString(strVal, bd);
    				}
    				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
    				try {
    					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
    				}
    				catch (UnsupportedOperationException ex) {
    					// A custom TypeConverter which does not support TypeDescriptor resolution...
    					return (descriptor.getField() != null ?
    							converter.convertIfNecessary(value, type, descriptor.getField()) :
    							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
    				}
    			}
    			//是否是多个bean的注入,比如参数类型是集合,map
    			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
    			if (multipleBeans != null) {
    				return multipleBeans;
    			}
    			//寻找装配候选对象
    			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    			if (matchingBeans.isEmpty()) {
    				if (isRequired(descriptor)) {//空的话,又是必须的,才会报异常
    					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    				}
    				return null;
    			}
    
    			String autowiredBeanName;//自动装配的bean名字
    			Object instanceCandidate;//装配实例
    
    			if (matchingBeans.size() > 1) {//有多个
    				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    				if (autowiredBeanName == null) {
    					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
    						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
    					}
    					else {
    
    						return null;
    					}
    				}
    				instanceCandidate = matchingBeans.get(autowiredBeanName);
    			}
    			else {//只有一个
    				// We have exactly one match.
    				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
    				autowiredBeanName = entry.getKey();
    				instanceCandidate = entry.getValue();
    			}
    
    			if (autowiredBeanNames != null) {
    				autowiredBeanNames.add(autowiredBeanName);
    			}
    			if (instanceCandidate instanceof Class) {//获取装配实例,也要进行getBean过程
    				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    			}
    			Object result = instanceCandidate;
    			if (result instanceof NullBean) {
    				if (isRequired(descriptor)) {//不存在,又是必须
    					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    				}
    				result = null;
    			}
    			if (!ClassUtils.isAssignableValue(type, result)) {//类型不匹配
    				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
    			}
    			return result;
    		}
    		finally {//处理完后恢复当前注入点
    			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    		}
    	}

DefaultListableBeanFactory的findAutowireCandidates寻找自动装配类型

这里会去寻找我们的容器里面是否有参数的类型,先把参数类型的bean定义中的所有bean名字找出来,创建一个LinkedHashMap集合,然后判断类型是不是内部的类型,是的话也要加进去。然后遍历候选名字集合,把非自引用的可以作为别人依赖的类型添加到集合中,如果集合为空,还要进行处理判断,比如是不是数组类型,集合类型,再做相应处理。

    protected Map<String, Object> findAutowireCandidates(
    			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    		//获取requiredType对应的bean名字数组
    		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    				this, requiredType, true, descriptor.isEager());
    		Map<String, Object> result = new LinkedHashMap<>(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;
    				}
    			}
    		}
    		for (String candidate : candidateNames) {//自定义的基本在这里
    			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
    				addCandidateEntry(result, candidate, descriptor, requiredType);//非自引用,且可以为其他类做自动装配的,就加入集合
    			}
    		}
    		if (result.isEmpty()) {//空的处理
    			boolean multiple = indicatesMultipleBeans(requiredType);
    			// Consider fallback matches if the first pass failed to find anything...
    			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
    			for (String candidate : candidateNames) {
    				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
    						(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
    					addCandidateEntry(result, candidate, descriptor, requiredType);
    				}
    			}
    			if (result.isEmpty() && !multiple) {
    				// Consider self references as a final pass...
    				// but in the case of a dependency collection, not the very same bean itself.
    				for (String candidate : candidateNames) {
    					if (isSelfReference(beanName, candidate) &&
    							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
    							isAutowireCandidate(candidate, fallbackDescriptor)) {
    						addCandidateEntry(result, candidate, descriptor, requiredType);
    					}
    				}
    			}
    		}
    		return result;
    	}

addCandidateEntry添加到候选集合里

如果是多元素集合和StreamDependencyDescriptor类型的,会去创建相应的bean,然后放入,否则就直接把类型放入进来。

    private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
    			DependencyDescriptor descriptor, Class<?> requiredType) {
    
    		if (descriptor instanceof MultiElementDescriptor) {
    			Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
    			if (!(beanInstance instanceof NullBean)) {
    				candidates.put(candidateName, beanInstance);
    			}
    		}
    		else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
    				((StreamDependencyDescriptor) descriptor).isOrdered())) {
    			Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
    			candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
    		}
    		else {
    			candidates.put(candidateName, getType(candidateName));
    		}
    	}

DependencyDescriptor的resolveCandidate

当我们解析出来要装配的类型的时候,就可以开始去真正的获取该类型的对象了,其实内部还是调用getBean的。

    	public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
    			throws BeansException {
    
    		return beanFactory.getBean(beanName);
    	}

大致的流程就分析到这里啦,很多细节还没深入,因为比较复杂,还是先把大致搞清楚在去琢磨细节比较好。下篇我们把基本的流程图总计下。

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值