Spring 5.x 源码之旅-28getBean详解十三populateBean一

深入Java多线程与依赖注入原理:从源码到实践

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

 

populateBean分段1

在填充属性前,还会给InstantiationAwareBeanPostProcessor的处理器处理,给他们机会让他们去修改bean实例,这里也是扩展点。如果处理postProcessAfterInstantiation方法会发false,那就会停止属性填充,跳出循环并返回,说明可以控制是否要进行填充,但是spring内部的处理器不会有处理,要处理还是要自定义去扩展处理器。

    boolean continueWithPropertyPopulation = true;//是否让InstantiationAwareBeanPostProcessor继续执行
    		// 在填充前还可以用InstantiationAwareBeanPostProcessors来修改bean
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {//非合成的
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    						continueWithPropertyPopulation = false;//停止处理
    						break;
    					}
    				}
    			}
    		}
    		if (!continueWithPropertyPopulation) {//如果停止处理就返回
    			return;
    		}

populateBean分段2

获取自动装配模式,默认是NO,如果有设置了,就会根据设置来进行装配。

    //获取属性值
    		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    		//获取自动装配模式,默认是no
    		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    			// Add property values based on autowire by name if applicable.
    			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
    				autowireByName(beanName, mbd, bw, newPvs);
    			}
    			// Add property values based on autowire by type if applicable.
    			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    				autowireByType(beanName, mbd, bw, newPvs);
    			}
    			pvs = newPvs;
    		}

populateBean分段3

这里会进行InstantiationAwareBeanPostProcessor处理器的postProcessProperties处理,

    //是否有InstantiationAwareBeanPostProcessors
    		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    
    		PropertyDescriptor[] filteredPds = null;
    		if (hasInstAwareBpps) {
    			if (pvs == null) {//创建PropertyValues
    				pvs = mbd.getPropertyValues();
    			}
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {//继续后置处理器处理
    				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    					if (pvsToUse == null) {
    						if (filteredPds == null) {
    							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    						}
    						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    						if (pvsToUse == null) {
    							return;
    						}
    					}
    					pvs = pvsToUse;
    				}
    			}
    		}
    		

ConfigurationClassPostProcessor内部类ImportAwareBeanPostProcessor的postProcessProperties

这个就是前面如果配置类有Configuration注解,会进行动态代理,会实现EnhancedConfiguration接口,里面有个setBeanFactory接口方法,会传入beanFactory

    @Override
    		public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
    			// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
    			// postProcessProperties method attempts to autowire other configuration beans.
    			if (bean instanceof EnhancedConfiguration) {
    				((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
    			}
    			return pvs;
    		}

CommonAnnotationBeanPostProcessor的postProcessProperties

这里就处理我们前面applyMergedBeanDefinitionPostProcessors处理注入注解元数据。

    	@Override
    	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    		InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    		try {
    			metadata.inject(bean, beanName, pvs);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    		}
    		return pvs;
    	}

InjectionMetadata的inject

遍历前面注册的InjectedElement,然后进行注入。

    	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    		Collection<InjectedElement> checkedElements = this.checkedElements;
    		Collection<InjectedElement> elementsToIterate =
    				(checkedElements != null ? checkedElements : this.injectedElements);
    		if (!elementsToIterate.isEmpty()) {
    			for (InjectedElement element : elementsToIterate) {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
    				}
    				element.inject(target, beanName, pvs);
    			}
    		}
    	}
InjectedElement的inject

进行属性或者方法注入,但是方法注入前会判断是否已经有设置值了,有设置就不会注入,直接返回了。

    		protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
    				throws Throwable {
    
    			if (this.isField) {//属性注入
    				Field field = (Field) this.member;
    				ReflectionUtils.makeAccessible(field);
    				field.set(target, getResourceToInject(target, requestingBeanName));
    			}
    			else {
    				if (checkPropertySkipping(pvs)) {
    					return;
    				}
    				try {//方法注入
    					Method method = (Method) this.member;
    					ReflectionUtils.makeAccessible(method);
    					method.invoke(target, getResourceToInject(target, requestingBeanName));
    				}
    				catch (InvocationTargetException ex) {
    					throw ex.getTargetException();
    				}
    			}
    		}
checkPropertySkipping

判断是否要略过属性注入,如果是定义的时候给定值了就忽略。

    protected boolean checkPropertySkipping(@Nullable PropertyValues pvs) {
    			Boolean skip = this.skip;
    			if (skip != null) {
    				return skip;
    			}
    			if (pvs == null) {
    				this.skip = false;
    				return false;
    			}
    			synchronized (pvs) {
    				skip = this.skip;
    				if (skip != null) {
    					return skip;
    				}
    				if (this.pd != null) {
    					if (pvs.contains(this.pd.getName())) {
    						// 给定了值了就忽略,直接返回
    						this.skip = true;
    						return true;
    					}
    					else if (pvs instanceof MutablePropertyValues) {//如果是可变的话,就注册到处理过的属性集合里
    						((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
    					}
    				}
    				this.skip = false;
    				return false;
    			}
    		}
ResourceElement的getResourceToInject

getResourceToInject是关键的方法,其实是InjectedElement的抽象方法,子类有不同的实现类,比如ResourceElementEjbRefElementWebServiceRefElement,当然我们就关注ResourceElement啦,其他自己有兴趣可以看。

这个方法首先判断注释元数据有没有Lazy注解,也就是懒加载,有的话会创建一个代理类,内部是用AOP代理工厂做的,细节后面说,然后有个getTarget代理方法,可以在需要时候调用获取。如果不是就直接getResource

    @Override
    		protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
    			return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
    					getResource(this, requestingBeanName));
    		}
CommonAnnotationBeanPostProcessor的getResource

先判断jndi的注入,然后才调用autowireResource,我们一般就是autowireResource

    protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
    			throws NoSuchBeanDefinitionException {
    
    		if (StringUtils.hasLength(element.mappedName)) {
    			return this.jndiFactory.getBean(element.mappedName, element.lookupType);
    		}
    		if (this.alwaysUseJndiLookup) {
    			return this.jndiFactory.getBean(element.name, element.lookupType);
    		}
    		if (this.resourceFactory == null) {
    			throw new NoSuchBeanDefinitionException(element.lookupType,
    					"No resource factory configured - specify the 'resourceFactory' property");
    		}
    		return autowireResource(this.resourceFactory, element, requestingBeanName);
    	}

autowireResource比较关键,我们后面再讲吧。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值