Spring源码深度解析(郝佳)-学习-数据转换-ConversionService源码解析一

20 篇文章 1 订阅
18 篇文章 0 订阅

为什么我们在xml配置的对象引用,Spring会帮我们实例化呢?为什么在xml配置的是一个字符串,Spring 却能帮我们转化成java对象中申明的属性类型呢?在比较新的Spring版本中与ConversionService有关,Spring 3.0 之前和PropertyEditor这个类相关,有兴趣的同学可以自行研究一下。今天,我们就来研究一下源码,Spring 是如何进行数据转换的。

先上示例

User.java

@Data
public class User {
   
}

Student.java

@Data
public class Student {
    private int score;
    private User user;
}

Test113.java

import com.alibaba.fastjson.JSON;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test113 {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring_101_200/config_111_120/spring113_conversion/spring113.xml");
        Student student = (Student) ctx.getBean("student");
        System.out.println(JSON.toJSONString(student));
    }
}

spring113.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <bean id="user" class="com.spring_101_200.test_111_120.test_113_conversion.User" >
      
     </bean>

    <bean id="student" class="com.spring_101_200.test_111_120.test_113_conversion.Student">
        <property name="score" value="10"></property>
        <property name="user" value="#{user}"></property>
    </bean>
</beans>

【结果输出】
{“score”:10,“user”:{}}
我们看到,我们在student对象中,得到了score的值是int类型的,而user对象也被封装进去了,那么Spring代码是如何实现的呢?
对于bean的解析过程,这里不再做过多的缀述,我们直接来切入正题,Bean对象的创建,属性是如何填充的

AbstractApplicationContext.java

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1.调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识 
        prepareRefresh();
        
        // 2.告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类 的refreshBeanFactory()方法启动
        // 在refresh()方法中 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 启动了Bean的注册
        // Bean定义资源的载入,注册过程,finishBeanFactoryInitialization() 方法是对注册后的Bean定义中的预实例化(lazy-init=false)
        // Spring 默认进行预实例化,即为true的Bean 进行处理的地方
        // 初始化 bean ,并进行 xml 文件的读取
        // obtainFreshBeanFactory 方法从字面的理解是获取 BeanFactory ,之前有说过,ApplicationContext 是对 BeanFactory
        // 的功能上基础上添加了大量的扩展应用,那么 obtainFreshBeanFactory 正是实现 BeanFactory 的地方,也就是经过这个函数之后
        // ApplicationContext 就已经拥有 BeanFactory 的全部功能 
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
         // 3.为BeanFactory配置容器,例如类加载器,事件处理器 ,为 BeanFactory 进行各种功能进行填充 
        prepareBeanFactory(beanFactory);

        try {
             // 4.为容器的某些子类指定特殊的Post事件处理器  
            postProcessBeanFactory(beanFactory);
            
             // 5.调用所有的注册的beanFactoryPostProcessor的bean ,激活各种 BeanFactory 处理器 
            invokeBeanFactoryPostProcessors(beanFactory);

             // 6.为BeanFactory注册Post事件处理器
            // 注册拦截 bean 创建 bean 处理器,这里只是注册,真正的调用在 getBean 时候 
            registerBeanPostProcessors(beanFactory);

 
             // 7.初始化信息源,和国际化相关 ,  为上下文初始化 Message源,即不同的语言的消息体,国际化处理 
            initMessageSource();

             // 8.初始化容器事件传播器 ,初始化应用消息广播器,并放入到"applicationEventMulticaster" bean 中 
            initApplicationEventMulticaster();

             // 9.调用子类的某些特殊bean的初始化方法 , 留给子类来初始化其他的 Bean 
            onRefresh();

             // 10.为事件传播器注册事件监听器 ,在所有的注册的 bean 中查找 Listener Bean ,注册到消息广播器中 
            registerListeners();
            
             // 11.初始化所有剩余的单例Bean 
            finishBeanFactoryInitialization(beanFactory);
            
             // 12.初始化容器的生命周期事件处理器,为发布容器的生命周期事件 , 完成刷新过程,通知生命周期处理器 lifecycleProcessor 刷新
            // 过程,同时发出 contextRefreshEvent 通知别人 
            finishRefresh();
        } catch (BeansException ex) {
             // 13.销毁已经创建的bean 
            destroyBeans();

             // 14.取消刷新操作,重置容器的同步标识 
            cancelRefresh(ex);
            
            throw ex;
        } finally {
             // 设置公共缓存 
            resetCommonCaches();
        }
    }
}

AbstractApplicationContext.java

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 这是Spring 3 新加的代码,为容器指定个转换服务(ConversionService)
    // 在对某些Bean属性进行转换时使用 
    if (beanFactory.containsBean("conversionService") &&
            beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
        LogUtils.info("finishBeanFactoryInitialization beanFactory constains conversionService");
        beanFactory.setConversionService(
                beanFactory.getBean("conversionService", ConversionService.class));
    }

    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);

    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // 为了使类型匹配,停止使用临时的类加载器 
    beanFactory.setTempClassLoader(null);

    // 缓存容器中所有的注册的BeanDefinition元数据,以防止被修改 , 冻结所有的 bean 的定义,说明注册的 bean 定义将不被修改
    // 或者进一步的处理 
    beanFactory.freezeConfiguration();

    // 对配置了lazy-init属性的单例模式的Bean进行预实例化处理 ,初始化剩下的单实例(非惰性的) 
    beanFactory.preInstantiateSingletons();
}

DefaultListableBeanFactory.java

 // 对配置了lazy-init属性的单例模式的Bean实例化
// 通过对lazy-init处理源码分析可以看出,如果设置了lazy-init属性,则容器在完成Bean定义的注册后,会通过getBean()方法触发指定的
// Bean 的初始化和依赖注入,如果前面所述,这样当应用程序第一次向容器索取所需要的Bean时,容器不再需要对Bean进行初始化的依赖注入
// 可直接从已经完成的实例化和依赖注入的Bean中取一个现在的Bean ,提高第一次获取Bean的性能
// 3 .初始化非延迟加载
// ApplicationContext 实现默认的行为就是在启动时将所有的单例 bean 提前进行实例化,提前实例化就意味着为初始化过程的一部分,
// ApplicationContext 实例会创建并配置所有的单例 bean ,通常情况下这是一件好事,因为这样在配置中的任何错误就会即刻被发现。
// 否则的话,可能要花几个小时甚至几天,而这个实例化的过程就是在 finishBeanFactoryInitialization 中完成
@Override
public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug("Pre-instantiating singletons in " + this);
	}
	List beanNames = new ArrayList(this.beanDefinitionNames);
	 // Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		 // 获取指定名称的Bean定义,合并父类的beanDefinition
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		 // Bean 不是抽象的,是单例模式的,且lazy-init属性配置为false
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			 // 如果指定的名称的Bean是创建容器的Bean
			if (isFactoryBean(beanName)) {
				 // FACTORY_BEAN_PREFIX="&",当Bean 名称前面加了&符号时,获取的是容器对象本身,而不是容器产生的Bean
				// 调用getBean 方法,触发Bean实例化,和依赖注入
				final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
				 // 标识是否需要预实例化
				boolean isEagerInit;
				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					 // 一个匿名的内部类
					isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
						@Override
						public Boolean run() {
							return ((SmartFactoryBean<?>) factory).isEagerInit();
						}
					}, getAccessControlContext());
				}
				else {
					isEagerInit = (factory instanceof SmartFactoryBean &&
							((SmartFactoryBean<?>) factory).isEagerInit());
				}
				if (isEagerInit) {
					 // 调用getBean()方法,触发Bean实例化和依赖注入
					getBean(beanName);
				}
			}
			else {
				getBean(beanName);
			}
		}
	}

	 // Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged(new PrivilegedAction() {
					@Override
					public Object run() {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}

AbstractBeanFactory.java

// 获取IoC容器中的指定名称的Bean

@Override
public Object getBean(String name) throws BeansException {
	// doGetBean才是真正的向Ioc容器中获取管理的Bean
	return doGetBean(name, null, null, false);
}

AbstractBeanFactory.java

@SuppressWarnings("unchecked")
protected  T doGetBean(
		final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
		throws BeansException {
	// 根据指定的名称获取被管理的Bean的名称,剥离指定的名称中对容器的相关依赖
	// 如果指定的是别名,将别名转换成规范的Bean的名称
	final String beanName = transformedBeanName(name);
	Object bean;
	// 检查缓存中或者实例工厂中是否有对应的实例
	// 为什么首先会使用这段代码呢?
	// 因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候,为了避免循环依赖
	// Spring 创建 bean 的原则是不等 bean 的创建完成就会将创建的 bean  的 ObjectFactory 提早曝光
	// 也就是将 ObjectBeanFactory  加入到缓存中,一旦下个 bean 创建的时候需要依赖上个 bean 则直接使用 ObjectFactory
	// 直接尝试从缓存中获取或者 singletonFactories 中的 ObjectFactory 中获取
	Object sharedInstance = getSingleton(beanName);
	
	// 先从缓存 中读取是否已经有被创建过的单例模式的bean
	// 对于单例模式的Bean,整个Ioc容器只创建一次,不需要重复的创建
	if (sharedInstance != null && args == null) {
		// 获取给定的Bean的实例对象,主要完成FactoryBean相关处理
		// 注意:BeanFactory是管理Bean的工厂,FactoryBean是创建对象的工厂Bean,两者之间是有很多的区别的 
		// 返回对应的实例 , 有个时候存在诸如 BeanFactory 的情况并不是直接返回实例本身而是返回指定方法返回的实例
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	} else {
		// 缓存中已经在有原型模式的Bean
		// 但是由于循环引用导致实例化对象失败
		// 只有在单例的情况下都会以尝试解析循环依赖,原型模式情况下,如果存在 A 中有 B 的属性,B中有 A的属性,那么当依赖
		// 注入的时候,就会产生当 A 还示创建完成的时候因为
		// 对 B 的创建再次返回创建 A ,造成我一依赖,也就是下面的情况
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// 对于Ioc容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否
		// 能在当前的BeanFactory中获取所需要的Bean,如果不能则委托当前的容器
		// 的父容器去查找 ,如果还是找不到,则沿着容器的继承体系向父容器中查找
		BeanFactory parentBeanFactory = getParentBeanFactory();
		//如果 beanDefinitionMap 中也就是在所有的已经加载的类中不包括 beanName,则尝试从 parentBeanFactory 中检测
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// 解析指定的Bean名称的原始名称
			String nameToLookup = originalBeanName(name);
			// 递归到 BeanFactory 中查找
			if (args != null) {
				// 委派父容器根据指定名称和显示的参数查找
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				// 委派父容器根据指定名称和类型查找
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}
		// 如果不是仅仅做类型检查则是创建 bean,这里需要进行记录
		if (!typeCheckOnly) {
			// 向容器标记指定的Bean是否已经被创建
			markBeanAsCreated(beanName);
		}

		try {
			//根据指定的Bean的名称获取其父级别的Bean的定义
			// 主要解决Bean继承子类和父类公共属性的问题,将存在 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition
			// 如果指定 BeanName 是子的 Bean 的话同时合并父类的相关属性
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);
			
			// 获取当前Bean所依赖的Bean的名称 , 如果存在依赖则需要递归实例化依赖的 bean
			String[] dependsOn = mbd.getDependsOn();
			//如果当前的Bean有依赖的Bean
			if (dependsOn != null) {
				for (String dependsOnBean : dependsOn) {
					if (isDependent(beanName, dependsOnBean)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
					}
					//把被依赖的Bean注册给当前的依赖的Bean 
					registerDependentBean(dependsOnBean, beanName);
					// 递归调用getBean()方法,获取当前的Bean的依赖的Bean
					getBean(dependsOnBean);
				}
			}
			
			// 创建单例模式的Bean的实例对象
			if (mbd.isSingleton()) {
				//这里使用了一个匿名的内部类创建Bean实例对象,并且注册给所依赖的对象
				sharedInstance = getSingleton(beanName, new ObjectFactory() {
					@Override
					public Object getObject() throws BeansException {
						try {
							//创建一个指定的Bean的实例对象,如果有父类继承,则合并子类和父类的定义
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// 显示的从容器中单例模式的Bean缓存中清除实例对象
							destroySingleton(beanName);
							throw ex;
						}
					}
				});
				//获取给定的Bean的实例对象
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}
			//Ioc容器创建原型模式的Bean的实例对象
			else if (mbd.isPrototype()) {
				// 原型模式(Prototype)每次都会创建一个新的对象
				Object prototypeInstance = null;
				try {
					//回调BeforePrototypeCreation()方法,默认的功能是在注册当前创建的原型对象
					beforePrototypeCreation(beanName);
					//创建指定的Bean的对象实例
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					//回调afterPrototypeCreation()方法,默认的功能是告诉Ioc容器不要再创建指定的Bean的原型对象
					afterPrototypeCreation(beanName);
				}
				//获取指定的Bean的实例对象
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}
			//如果要创建的对象既不是单例模式,也不是原型模式,则根据Bean定义资源中
			// 配置的生命周期范围,选择实例化Bean的合法方法,这种方法在WEb应用程序中
			//比较常用,如request,session,application等生命周期
			else {
				String scopeName = mbd.getScope();
				final Scope scope = this.scopes.get(scopeName);
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
				}
				try {
					// 这里又使用了一个匿名的内部类,获取 一个指定的生命周期的实例
					Object scopedInstance = scope.get(beanName, new ObjectFactory() {
						@Override
						public Object getObject() throws BeansException {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						}
					});
					// 获取指定的Bean的实例对象
					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName,
							"Scope '" + scopeName + "' is not active for the current thread; " +
							"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
							ex);
				}
			}
		}
		catch (BeansException ex) {
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
	}

	//  检查需要的类型是否符合 bean 的实际类型
	if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
		try {
			return getTypeConverter().convertIfNecessary(bean, requiredType);
		}
		catch (TypeMismatchException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to convert bean '" + name + "' to required type [" +
						ClassUtils.getQualifiedName(requiredType) + "]", ex);
			}
			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
	}
	return (T) bean;
}

Spring 加载 bean 的过程
    1.转换对应的 beanName
    2.或许很多的人不理解转换对应的 beanName 是什么意思,传入的参数 name 就是 beanName 吗?其实不是,这个传入的参数可能是别名,也可能是
其实不是,这里传入的参数可能是别名,也可能是 FactoryBean,所以需要进行一系列的解析,这些解析的内容包括如下内容
去除 FactoryBean 的修饰符,也就是如果 name="&aa" ,那么会首先去除&而使得 name = “aa” ,
取指定的 alias 所表示的最终的 beanName ,例如别名 A 指向别名 B的 bean 则返回 B ;若别名 A 指向别名 B,别名 B 又指向别名 C的Bean
则直接返回 C
单例的在 Spring 的同一个容器内只会被创建一次,后续再获取 Bean ,就直接从单例缓存中获取了,当然,这里也只是尝试加载,首先会尝试
从缓存中加载,如果加载不成功,则尝试从 singletonFactroy 中加载,因为为创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候
为了避免循环依赖,在 Spring 中创建 Bean 的原则是不等 bean 创建完成就会将创建的 bean 的 ObjectBeanFactory 提前曝光加入到缓存中的
一旦下一个 bean 创建的时候需要依赖上一个 bean 则直接使用BeanFactory
    3. bean 的实例化
如果从缓存中得到 bean 的原始状态,则需要对 bean 进行实例化,这里有必要强调一下, 缓存中的记录只是原始的 bean 的状态,并不一定是我们
最终想要的 bean ,举个例子,但是我们真正需要的是工厂 bean 中定义的 factory-method 方法中返回的 bean,而 getObjectForBeanInstance 就完成
了这个工作,后续会详细的讲解
    4.原型模式的依赖检查
只有在单例的情况下,才会尝试解决的循环依赖,如果存在 A中有 B 的属性,B 中有 A 的属性,那么当依赖注入的时候,就会产生 A 还未创建
完成的时候,因为对于 B 的创建再次返回创建 A ,造成循环依赖,也就是情况,isPrototypeCurrentlyInCreation(beanName) 判断 true
检测 parentBeanFactory
从代码的上来看,如果缓存 没有数据的话,直接转到父类的工厂上去加载了,这是为什么呢?
可能读者会忽略一个很重要的判断条件,parentBeanFactory !=null && !containsBeanDefinition(beanName)
,parentBeanFactory !=null ,parentBeanFactory 如果为空,则其他的一切都是浮云,但是!containsBeanDefinition(beanName) 就比较
重要了,它是在检测如果当前加载的 xml 配置文件中不包含 beanName 所对应的配置,就只能到 parentBeanFactory 去尝试一下,然后再去
递归的调用 getBean 方法
     6.将存储的 xml 配置文件中的 GenericBeanDefinition 转换成 RootBeanDefinition 中的,但是所有的 Bean后续处理都是针对
RootBeanDefinition的,所以这里需要转换,转换的同时如果父类 bean 不为空的话,则会一并合并父类的属性
     7.寻找依赖,因为 bean 初始化的过程很可能是会用到某些属性的,而某些属性很可能是动态配置的,并且配置成依赖于其他的 bean , 那么
这个时候就有必要加载依赖的bean ,所以,在 Spring 的加载顺序中,在初始化某一个 bean 的时候,首先会初始化这个 bean 所对应的依赖
    8.针对不同的 scope 进行 bean 的创建
我们都知道,在 Spring 中存在着不同的 scope ,其中默认的是 singleton ,但是还有一些其他的配置,诸如 prototype ,request 之类的
在这个步骤中,Spring会根据不同的配置进行不同的初始化策略
    9. 程序到这里返回 bean后已经基本的结果了,通常对该方法的调用参数 requiredType 是为空的,但是可能会存在这样的一种情况,返回的 bean
其实是 String 类型的,但是 requiredType 传入的是 Integer类型,那么这个时候本步骤会直到了作用,它的功能是将返回bean 转换成
requiredType 所指定的类型,当然,String 转换为 Integer 是最简单的一种转换,在 Spring 提供了各种各样的转换器,用户也可以自己定义
自己的转换器来满足需求
经过上面的步骤后bean 的加载已经结束了,这个时候就可以返回我们需要的 bean 了,直观的反映整个过程,其中最重要的步骤就是8,针对不同的
scope 进行 bean 的创建,你会看到各种常用的 Spring中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求
经过上面的步骤后,bean 的加载已经结束,这个时候就可以返回我们所需要的 bean 了,

    真正的实现向Ioc容器获取Bean的功能,也是就触发依赖注入的地方
通过对IOC容器的获取Bean的的分析,我们可以看到,在Spring中,如果Bean定义为单例模式(Singleton)的,容器在创建之前先从缓存中查找
以确保整个容器中只存在一个实例对象时,如果Bean定义为原型模式,则容器每次都会创建一个新的的实例对象,除此之外,Bean定义还可以指定其生命
周期范围
    上面的源码只定义了根据Bean定义的不同模式采取的创建Bean实例对象的不同策略,具体的Bean实例对象创建过程由实现了ObjectFactory接口匿名
内部类createBean()方法完成,ObjectFactory接口使用了委派模式,具体的Bean实例创建过程交由其实现类AbstractAutowireCapableBeanFactory
完成,下面我们继续分析AbstractAutowireCapableBeanFactory的createBean()方法的源码,理解 创建Bean实例具体的过程

DefaultSingletonBeanRegistry.java

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	// 全局变量需要同步
	synchronized (this.singletonObjects) {
		// 首先检查对应的bean 是否已经加载过,因为 singleton 模式其实就是复用以创建 bean ,这一步是必须的
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果为空才可以进行 singletonObject == null
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName,
						"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
						"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			// 在创建单例前调用
			beforeSingletonCreation(beanName);

			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet();
			}
			try {
				// 初始化 bean
				singletonObject = singletonFactory.getObject();
				newSingleton = true;
			}
			catch (IllegalStateException ex) {
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					throw ex;
				}
			}
			catch (BeanCreationException ex) {
				if (recordSuppressedExceptions) {
					for (Exception suppressedException : this.suppressedExceptions) {
						ex.addRelatedCause(suppressedException);
					}
				}
				throw ex;
			}
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				// 在单例创建后调用
				afterSingletonCreation(beanName);
			}

			if (newSingleton) {
				// 加入缓存中
				addSingleton(beanName, singletonObject);
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}
}

      之前我们已经讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例 bean ,就需要从头开始 bean 的加载过程了,而 Spring
中使用 getSingleton 的重载方法实现了 bean 的加载过程
      上述代码中其实使用了回调方法,使得程序可以在单例创建前后做一些准备及处理操作,而真正的获取单例 bean 的方法其实并不是在此方法中实现在
其实逻辑是在 ObjectFactory 类型的实例 singleFactory 中实现的,而这些准备及处理操作包括如下内容:
      1.检查缓存中是否已经加载过
      2.若没有加载,则记录 beanName 的正在加载状态
      3.加载单例前记录加载状态

可能你会觉得 beforeSingletonCreation 方法是空实现,里面没有任何逻辑,但是其实不是,这个函数中做了一个很重要的操作,记录加载状态,也就是通过 this.singletonsCurrentlyIn 这个函数做一个很重要的操作,记录加载状态,也就是通过 this.singletonsCurrentlyInCreation.add(beanName )
将当前正要创建的 bean 记录在缓存中,这样便可以对我一依赖进行检测

protected void beforeSingletonCreation(String beanName ){
      if(!this.inCreationCheckExclusions.contains(beanName ) &&             !this.singletons.CurrentlyInCreation.add(beanName )){
            throw new BeanCurrentlyInCreationException(beanName);
      }
}
      4.通过调用参数传入的 ObjectFacotry 的个体 Object 方法实例化 bean
      5.加载单例后的处理方法调用
同步骤3的记录加载状态相似,当 bean 加载结束后需要移除缓存中对该 bean 的正在加载状态记录
      protected void afterSingletonCreation(String beanName ){
            if(!this.inCreationCheckExclusions.contains(beanName) &&                   !this.singletons.CurrentlyInCreation.remove(beanName)){
                  throw new IllegalStateException(“Single '” + beanName + " ’ isnt current in creation ")
            }
      }
      6.将结果记录至缓存中并删除加载bean 的过程中所记录的各种辅助状态
protected void addSingleton(String beanName ,Object singletonObject){
synchronized(this.singletonObjets){
            this.singletonObjects.put(beanName,(singletonObject == null ? singletonObject:NULL_OBJECT));
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registereSingletons.add(beanName);
      }
}
      7.返回处理结果
虽然我们已经从外部了解了加载 bean 的逻辑架构,但现在我们还并没有开始对 bean 的加载功能的探索,之前反映到过,bean 的加载逻辑其实
是在传入的 ObjectFactory 类型参数 singletonFactory 中定义的,我们反推参数的获取 ,得到如下的代码
sharedInstance=getSingleton(beanName ,new ObjectFactory (){
      public Object getObject() throws BeanException{
            try{
                  return createBean(beanName ,mbd,args);
            }catch(Exception ex ){
                  destroySingleton(beanName);
                  throw ex;
            }
      }
});
ObjectFactory 的核心的部分其实只是调用了 createBean的方法,所以我们还需要到 createBean 方法中追寻真理

AbstractAutowireCapableBeanFactory.java

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// 判断需要创建的Bean是否可以实现实例化,即是否可以通过当前的类加载器加载
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// 校验和准备Bean方法的覆盖
	try {
		// 验证及准备覆盖方法
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// 如果Bean配置了初始化和初始化后的处理器,则试图返回一个需要创建的Bean的代理对象
		// 	 5.5.2 实例化的前置处理
		//			在真正的调用doCreate方法创建bean的实例前使用这样的一个方法resolveBeforeInstantiation(beanName,mdb)对BeanDefinition中的属性
		//			做些前置处理,当然,无论是其中是否有相应的逻辑实现我们都可以理解的,因为真正的逻辑实现前后留下处理函数也是可扩展的一种体现
		//			但是并不是最的不要的,在函数中还提供了一个短路判断,这才是最关键的部分。
		// 当经过前置处理后返回的结果不为空。那么会直接略过后续的bean的创建而直接返回结果,这一特性虽然很容易被忽略,但是却起着
		// 至关重要的作用,我们熟知的AOP功能就是基于这里判断的
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}
	// 创建Bean的入口
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	if (logger.isDebugEnabled()) {
		logger.debug("Finished creating instance of bean '" + beanName + "'");
	}
	return beanInstance;
}

AbstractAutowireCapableBeanFactory.java

 /**
 *  尽管日志与异常的内容非常的重要,但是在阅读源码的时候似乎大部分的人都会直接忽略掉,在此深入探讨日志及异常的设计,
 *  1.如果是单例,则需要首先清除缓存
 *  2.实例化 bean ,将 beanDefinition 转换成 BeanWrapper
 *  3.转换是一个复杂的过程,但是我们可以尝试要搬大致的功能,如下所示
 *  如果存在工厂方法,则使用工厂方法进行初始化
 *  一个类有多个构造函数,每个构造函数都有不同的参数,所需要的根据参数锁定构造函数并进行初始化
 *  如果既不存在工厂方法也不存在带有参数的构造方法,则使用默认构造函数进行 bean 的实例化
 *  3.MergedBeanDefinitionPostProcessor 的应用
 *  bean 的合并后处理,Autowired 注解正是通过此方法实现诸如类型的预解析
 *  4.依赖处理
 *  在 Spring 中会有循环依赖的情况,例如: 当 A 中含有 Bean 的属性, 而 B 中又含有 A的属性时就构成一个循环依赖,此时如果 A 和 B
 *   都是单例,那么在 Spring 中处理方式就是当创建 B 的时候,涉及自动注入 A 的步骤时,并不是直接去再次创建 A ,而是通过放入到缓存中的
 *   ObjectFactory 来创建实例,这样就解决了循环依赖的问题
 *
 *  5. 属性填充,将所有的属性填充至 bean 的实例中
 *  6.循环依赖的各种检查
 *  之前反映到过,在 Spring 中要解析的循环依赖只是对单例有效,而对于 prototype 的 bean ,Spring 没有好的解决办法,唯一要做的就是抛出
 *  异常,在这个步骤里面会检测已经加载的 bean 是否已经出现了依赖循环,并判断是否需要抛出异常
 *  7.注册 DisposableBean
 *  	  如果配置了 destory-method , 这里需要注册以便于在销毁时候调用
 *  8.完成创建并返回
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

	 // 封装被创建物Bean对象
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		 // 根据指定的 bean 使用对应的策略创建新的实例,如 : 工厂方法,构造函数,自动注入,简单的初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
	 // 获取实例化Bean对象的类型
	Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

	 // 调用PostProcessor 后置处理器
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			// 应用 MergedBeanDefinitionPostProcessor
			// bean的合并处理,Autowired注解正是通过此方法实现诸如类型的预解析
			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			mbd.postProcessed = true;
		}
	}

	 // 向容器中缓存单例模式的Bean对象,以防止循环使用
	// 是否需要提早曝光,单例& 允许循环依赖&  当前 bean 正在创建中,检测循环依赖
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isDebugEnabled()) {
			logger.debug("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		 // 这里是一个匿名的内部类,为了防止循环引用,尽早的有对象引用
		// 为了避免后期的循环依赖,可以在 bean 的初始化完成前将创建的实例 BeanFactory 加入到工厂中
		addSingletonFactory(beanName, new ObjectFactory() {
			@Override
			public Object getObject() throws BeansException {
				 // 对 bean 再一次依赖引用,主要应用 SmartInstantiationAwareBeanPostProcessor ,
				// 其中我们熟知的 AOP 就是这里将 advice 动态织入bean 中,若没有则直接返回 bean ,不做任何处理
				return getEarlyBeanReference(beanName, mbd, bean);
			}
		});
	}

	// Bean对象的初始化,依赖注入在些触发
	// 这个exposedObject对象在初始化完成之后返回依赖注入完成后的Bean
	Object exposedObject = bean;
	try {
		// 将Bean实例对象封装,并且将Bean定义占的配置属性值赋给实例对象,对bean属性进行依赖注入
		// Bean实例对象的依赖注入完成后,开始对Bean实例对象进行初始化,为Bean实例对象应用BeanPostProcessor后置处理器
		// 对 bean 进行填充,将各个属性值注入,其中可能存在依赖于其他的 bean 的属性,则会递归的初始依赖 bean
		
		// 为什么构造器注入的时候会出现循环依赖问题而属性注入不会出现循环依赖问题?
		// 在使用构造器注入时,会在此处产生递归操作,在第四层创建A时DefaultSingletonBeanRegistry的beforeSingletonCreation方法中会报错
		//		因为DefaultSingletonBeanRegistry的this.singletonFactories中没有A的bean缓存。所以在beforeSingletonCreation中便会报错。
		//		那么为什么用属性注入时就不会报错呢?因为this.singletonFactories缓存发生在当前方法的addSingletonFactory行,而属性注入的递归发生在
		// 这一行,也就是说 先进行了缓存。而构造器注入时 还没来得及缓存就已经递归到下一层了。
		// 属性填充
		populateBean(beanName, mbd, instanceWrapper);
		if (exposedObject != null) {
			 // 初始化Bean对象
			// 调用初始化方法,比如 init-method
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

	if (earlySingletonExposure) {
		 // 获取指定名称的已经注册的单例模式的Bean对象,earlySingletonReference 只有检测到你有循环依赖的情况下才会不为空
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			 // 根据名称获取已经注册的Bean和正在实例化的Bean是不是同一个
			// 如果 exposedObject  没有被初始化方法中被改变,也就是没有被增强
			if (exposedObject == bean) {
				// 当前实例化的了Bean初始化完成
				exposedObject = earlySingletonReference;
			}
			 // 当前Bean依赖其他的Bean,并且当发生循环引用时不允许创建新的实例对象
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
				 // 获取当前的Bean所依赖的其他的Bean
				for (String dependentBean : dependentBeans) {
					 // 对依赖的Bean进行类型检查 
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				 /**
				 * 因为 bean 创建后其所依赖的 bean 一定是已经被创建了的
				 * actualDependentBeans 不为空则表示当前的 bean 创建后其依赖的 bean 却没有全部的创建完,也就是说存在循环依赖
				 */
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	try {
		 // 注册完成依赖注入的Bean
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}

到这里,我们终于看到了属性填充的方法populateBean,前面的一系列的介绍,只是说明bean是如何创建的。而属性填充,才是我们今天重点研究的对象。

AbstractAutowireCapableBeanFactory.java

/**
 * 	在前面的分析中我们已经了解到了Bean依赖注入主要分成两个步骤,首先调用createBeanInstance()方法生成Bean所包含的
 *           java对象实例,然后调用populateBean()方法对Bean属性的依赖注入进行处理
 *
 *           前面已经分析了容器初始化生成Bean所包含的java实例对象的过程,下面继续分析生成对象后,Spring Ioc容器是如何的将Bean
 *           的属性依赖关系注入到Bean实例化对象并设置好的,
 *Spring Ioc 容器提供了两种管理Bean依赖关系的方式
 * 1.显示管理:通过BeanDefintion的属性值和构造方法实现Bean依赖关系管理
 * 2.autowiring: Spring ioc 容器有依赖自动装配的功能,不需要对Bean属性的依赖关系做显示的声明,只需要配置好autowing属性,Ioc容器
 * 会自动的使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中的Bean , 从而自动的完成依赖注入
 * 容器对Bean 的自动装配发生在容器依赖注入的过程,在对Spring IOc容器的依赖注入的源码分析时,我们已经知道容器对Bean 实例对象的依赖
 * 属性注入发生在AbstractAutoWireCapabelBeanFactory类的populateBean()方法,下面的程序就分析autowiring原理
 *
 * 应用程序第一次通过getBean()方法配置了lazy-init预实例化,属性例外,向Ioc容器索取Bean时,容器创建Bean实例对象,并且对Bean
 * 实例对象进行属性依赖注入,AbstractAutoWireCapableBeanFactory的populateBean()方法实现了属性的依赖注入的功能
 * 将Bean 属性设置到生成的实例对象上
 * 
 *populateBean  函数中的提供了这样的处理流程
 *           1.InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 函数的应用,此函数可以控制程序是否
 *           继续进行属性填充
 *           2.根据注入的类型(byName/byType) ,提取依赖的 bean ,并统一存入 propertyValues 中
 *           3. 应用 InstantiationAwareBeanPostProcessor 处理器 postProcessPropertyValues 方法 对属性获取完毕填充前对属性进行
 *           再次处理,典型的应用是 RequiredAnnotationBeanPostProcessor 类中的属性验证
 *           4.将所有的 PropertyValues 中的属性填充到 BeanWrapper 中
 */
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
	PropertyValues pvs = mbd.getPropertyValues();

	if (bw == null) {
		if (!pvs.isEmpty()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
			// 如果没有属性填充,则直接跳过
			return;
		}
	}
	boolean continueWithPropertyPopulation = true;
	// 给 InstantiationAwareBeanPostProcessors  最后一次机会属性设置前来改变 bean
	// 如:可以用来支持属性注入的类型
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// 返回值是否继续填充 bean
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					continueWithPropertyPopulation = false;
					break;
				}
			}
		}
	}
	// 如果后处理器发出停止填充的命令则终止后续执行
	if (!continueWithPropertyPopulation) {
		return;
	}
	// 获取容器在解析Bean定义资源为BeanDefinition设置属性值
	// 处理依赖注入,首先处理autowing自动装配的依赖注入
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// 根据Bean 名称进行autowiring自动装配处理
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// 根据Bean 类型进行autowiring自动装配处理
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			// 根据类型自动注入
			autowireByType(beanName, mbd, bw, newPvs);
		}

		pvs = newPvs;
	}

	// 对非autowiring的属性进行依赖注入处理 ,后处理器已经初始化
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// 需要依赖检查
	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

	if (hasInstAwareBpps || needsDepCheck) {
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// 对所有的需要依赖检查的属性进行后处理
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return;
					}
				}
			}
		}
		if (needsDepCheck) {
			//依赖检查,对应的 depends-on 属性,3.0 已经弃用此属性
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
	}
	// 对属性进行注入
	applyPropertyValues(beanName, mbd, bw, pvs);
}

AbstractAutowireCapableBeanFactory.java


/**
 *            解析并注入依赖属性的过程
 *            从这个代码中可以看出,属性的注入过程分成以下的两种情况
 *            1.属性值的类型不需要强制转换时,不需要解析属性值进,直接进行依赖注入
 *            2.属性类型需要进行强制转换时,如对其他的对象引用等,首先需要解析属性值,然后对解析后的属性进行依赖注入
 *            对属性的解析是在BeanDefinitionValueResolver类的resolverValueNecessary()方法中进行的的,对属性值的依赖注入是通过
 *            bw.setPropertyValues()方法来实现
 *
 *
 *            程序运行到这里已经完成了对所有的注入属性的获取,但是获取 属性是以 PropertyValues 的形式存在,还并没有应用到
 *            已经实例化的 bean 中,这一工作是在 applyPropertyValues 中
 *
 *
 */
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
	if (pvs == null || pvs.isEmpty()) {
		return;
	}
	// 封装属性值
	MutablePropertyValues mpvs = null;
	List original;

	if (System.getSecurityManager() != null) {
		if (bw instanceof BeanWrapperImpl) {
			// 设置安全上下文,jdk安全机制
			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
		}
	}

	if (pvs instanceof MutablePropertyValues) {
		mpvs = (MutablePropertyValues) pvs;
		// 如果 mpv 中的值已经被转换成对应的类类型,那么可以直接设置到 beanWrapper 中
		if (mpvs.isConverted()) {
			// Shortcut: use the pre-converted values as-is.
			try {
				// 为实例化对象设置属性值
				bw.setPropertyValues(mpvs);
				return;
			}
			catch (BeansException ex) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Error setting property values", ex);
			}
		}
		// 获取属性值对象的原始类型值
		original = mpvs.getPropertyValueList();
	}
	else {
		// 如果 pvs 并不是使用 MutablePropertyValues 封装类型,那么直接使用原始的属性获取方法
		original = Arrays.asList(pvs.getPropertyValues());
	}
	//获取用户自定义类型转换
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}
	// 创建一个Bean定义属性值解析器,将Bean定义中的属性值解析为Bean实例对象的实际值 
	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
	// 为属性解析创建一个副本,将副本数据注入实例对象
	List deepCopy = new ArrayList(original.size());
	boolean resolveNecessary = false;
	// 遍历属性,将属性转换为对应的类的对应的属性类型
	for (PropertyValue pv : original) {
		// 属性值不需要转换
		if (pv.isConverted()) {
			deepCopy.add(pv);
		}
		// 属性值需要转换
		else {
			String propertyName = pv.getName();
			// 原始属性值,即转换之前的属性值
			Object originalValue = pv.getValue();
			// 转换的属性值,例如将引用转换成Ioc容器中的实例化对象的引用
			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
			// 转换之后的属性值
			Object convertedValue = resolvedValue;
			// 属性值是否可以转换,如果属性有属性描述器,并且属性名中没有 . 
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			if (convertible) {
				// 使用用户自定义类型转换器进行转换
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
			}

			// 存储转换之后的属性值,避免每次属性注入的时候转换工作
			if (resolvedValue == originalValue) {
				if (convertible) {
					// 设置属性转换之后的值
					pv.setConvertedValue(convertedValue);
				}
				deepCopy.add(pv);
			}
			// 属性是可转换的,且属性原始值是字符串类型,属性的原始类型值不是动态生成,属性的原始值不是集合或者数组类型的
			else if (convertible && originalValue instanceof TypedStringValue &&
					!((TypedStringValue) originalValue).isDynamic() &&
					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
				pv.setConvertedValue(convertedValue);
				// 重新封装属性值
				deepCopy.add(pv);
			}
			else {
				resolveNecessary = true;
				deepCopy.add(new PropertyValue(pv, convertedValue));
			}
		}
	}
	if (mpvs != null && !resolveNecessary) {
		// 标记属性值已经转换过了
		mpvs.setConverted();
	}

	// 进行属性的依赖注入,
	try {
		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
	}
}	

BeanDefinitionValueResolver.java

/**
 *	容器对属性进行依赖注入时,如果发现属性需要进行类型转换,例如属性值是容器中另一个Bean实例对象的引用,则容器首先需要根据属性值
 *进行解析出所引用的对象,然后,才能将该引用的对象注入到目标实例的属性上,对属性的解析由resolveValueIfNecessary()方法的实现,其源码
 * 如下
 *
 * 解析属性值,对注入类型的进行转换
 *
 *
 * 通过下面的代码分析,我们明白了Spring 是如何通过引用类型,内部类及集合类型的属性进行分析的,解析完成之后,就可以进行依赖注入了
 * ,依赖注入的过程就是将Bean对象实例设置到它们所依赖的Bean的属性上,真正的依赖注入是通过bw.setPropertyValues()方法实现的,
 * 该方法也使用了委派模式,在BeanWrapper接口中定义了方法声明,依赖注入的具体的实现交由其实现类BeanWrapperImpl完成的,
 * 下面我们根据BeanWrappperImpl类中依赖注入相关的代码来完成
 *
 */

public Object resolveValueIfNecessary(Object argName, Object value) {
	// 对引用类型的属性值进行解析
	if (value instanceof RuntimeBeanReference) {
		RuntimeBeanReference ref = (RuntimeBeanReference) value;
		// 调用引用类型属性的解析方法
		return resolveReference(argName, ref);
	}
	// 对引用容器中的另一个Bean名称属性进行解析
	else if (value instanceof RuntimeBeanNameReference) {
		String refName = ((RuntimeBeanNameReference) value).getBeanName();
		refName = String.valueOf(doEvaluate(refName));
		// 从容器中获取指定名称的Bean
		if (!this.beanFactory.containsBean(refName)) {
			throw new BeanDefinitionStoreException(
					"Invalid bean name '" + refName + "' in bean reference for " + argName);
		}
		return refName;
	}
	// 对Bean的类型的属性进行解析,主要是指Bean的内部类
	else if (value instanceof BeanDefinitionHolder) {
		BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
		return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
	}

	else if (value instanceof BeanDefinition) {
		BeanDefinition bd = (BeanDefinition) value;
		String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
				ObjectUtils.getIdentityHexString(bd);
		return resolveInnerBean(argName, innerBeanName, bd);
	}
	// 对集合数组类型的属性进行解析
	else if (value instanceof ManagedArray) {
		ManagedArray array = (ManagedArray) value;
		// 获取数组的类型
		Class<?> elementType = array.resolvedElementType;
		if (elementType == null) {
			String elementTypeName = array.getElementTypeName();
			if (StringUtils.hasText(elementTypeName)) {
				try {
					// 使用反射机制创建指定类型的对象
					elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
					array.resolvedElementType = elementType;
				}
				catch (Throwable ex) {
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Error resolving array type for " + argName, ex);
				}
			}
			// 没有获取到数组的类型,也没有获取到元素类型
			// 则直接设置数组的类型为Object
			else {
				elementType = Object.class;
			}
		}
		return resolveManagedArray(argName, (List<?>) value, elementType);
	}
	// 解析List类型的属性值
	else if (value instanceof ManagedList) {
		return resolveManagedList(argName, (List<?>) value);
	}
	// 解析set类型的属性值
	else if (value instanceof ManagedSet) {
		return resolveManagedSet(argName, (Set<?>) value);
	}
	// 解析map类型的属性值
	else if (value instanceof ManagedMap) {
		return resolveManagedMap(argName, (Map<?, ?>) value);
	}
	// 解析props类型的属性值,props其实就是key 和value均为字符串的map
	else if (value instanceof ManagedProperties) {
		Properties original = (Properties) value;
		// 创建一个副本,作为解析后的返回值
		Properties copy = new Properties();
		for (Map.Entry<Object, Object> propEntry : original.entrySet()) {
			Object propKey = propEntry.getKey();
			Object propValue = propEntry.getValue();
			if (propKey instanceof TypedStringValue) {
				propKey = evaluate((TypedStringValue) propKey);
			}
			if (propValue instanceof TypedStringValue) {
				propValue = evaluate((TypedStringValue) propValue);
			}
			copy.put(propKey, propValue);
		}
		return copy;
	}
	// 解析字符串类型的属性值
	else if (value instanceof TypedStringValue) {
		TypedStringValue typedStringValue = (TypedStringValue) value;
		Object valueObject = evaluate(typedStringValue);
		try {
			// 获取属性的目标类型
			Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
			if (resolvedTargetType != null) {
				// 对目标类型的属性进行解析,递归调用
				return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
			}
			// 如果没有获取属性的目标对象,则按照Object类型返回
			else {
				return valueObject;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					this.beanDefinition.getResourceDescription(), this.beanName,
					"Error converting typed String value for " + argName, ex);
		}
	}
	else {
		return evaluate(value);
	}
}

BeanDefinitionValueResolver.java

protected Object evaluate(TypedStringValue value) {
	Object result = doEvaluate(value.getValue());
	if (!ObjectUtils.nullSafeEquals(result, value.getValue())) {
		value.setDynamic();
	}
	return result;
}

BeanDefinitionValueResolver.java

private Object doEvaluate(String value) {
	return this.beanFactory.evaluateBeanDefinitionString(value, this.beanDefinition);
}

AbstractBeanFactory.java

protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {
	if (this.beanExpressionResolver == null) {
		return value;
	}
	Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);
	return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}

StandardBeanExpressionResolver.java

@Override
public Object evaluate(String value, BeanExpressionContext evalContext) throws BeansException {
	// value 为 null 或空字符串
	if (!StringUtils.hasLength(value)) {
		return value;
	}
	try {
		// 尝试从缓存中读取指定的表达式
		Expression expr = this.expressionCache.get(value);
		if (expr == null) {
			// 使用表达式解析器解析此表达式
			expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
			// 加入缓存
			this.expressionCache.put(value, expr);
		}
		// 读取表达式解析上下文
		StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
		if (sec == null) {
			// 初始化解析上下文
			sec = new StandardEvaluationContext();
			sec.setRootObject(evalContext);
			// 加载一系列的属性访问器
			sec.addPropertyAccessor(new BeanExpressionContextAccessor());
			sec.addPropertyAccessor(new BeanFactoryAccessor());
			sec.addPropertyAccessor(new MapAccessor());
			sec.addPropertyAccessor(new EnvironmentAccessor());
			sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
			sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
			// 类型转换服务不为空,则将其写入 StandardEvaluationContext 中
			ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
			if (conversionService != null) {
				sec.setTypeConverter(new StandardTypeConverter(conversionService));
			}
			// 允许子类实现自定义配置的钩子函数
			customizeEvaluationContext(sec);
			// 写入缓存
			this.evaluationCache.put(evalContext, sec);
		}
		// 在标准的解析上下文中解析此表达式
		return expr.getValue(sec);
	}
	catch (Exception ex) {
		throw new BeanExpressionException("Expression parsing failed", ex);
	}
}

TemplateAwareExpressionParser.java

@Override
public Expression parseExpression(String expressionString, ParserContext context)
		throws ParseException {
	if (context == null) {
		context = NON_TEMPLATE_PARSER_CONTEXT;
	}

	if (context.isTemplate()) {
		return parseTemplate(expressionString, context);
	}
	else {
		return doParseExpression(expressionString, context);
	}
}

TemplateAwareExpressionParser.java

private Expression parseTemplate(String expressionString, ParserContext context)
		throws ParseException {
	if (expressionString.length() == 0) {
		return new LiteralExpression("");
	}
	Expression[] expressions = parseExpressions(expressionString, context);
	if (expressions.length == 1) {
		return expressions[0];
	}
	else {
		return new CompositeStringExpression(expressionString, expressions);
	}
}

TemplateAwareExpressionParser.java

/**
 *使用配置的解析器解析给定表达式字符串的助手
 */
private Expression[] parseExpressions(String expressionString, ParserContext context)
		throws ParseException {
	List expressions = new LinkedList();
	// 读取表达式前缀
	String prefix = context.getExpressionPrefix();
	// 读取表达式后缀
	String suffix = context.getExpressionSuffix();
	// 起始索引
	int startIdx = 0;
	// 起始索引 < 表达式长度
	while (startIdx < expressionString.length()) {
		// 计算前缀索引
		int prefixIndex = expressionString.indexOf(prefix, startIdx);
		// 前缀索引 > 起始索引
		if (prefixIndex >= startIdx) {
			// #{} 之前存在常量字符串,则创建字面值表达式并写入 expressions
			if (prefixIndex > startIdx) {
				expressions.add(createLiteralExpression(context,
						expressionString.substring(startIdx, prefixIndex)));
			}
			// 计算前缀之后的索引
			int afterPrefixIndex = prefixIndex + prefix.length();
			// 计算后缀索引
			int suffixIndex = skipToCorrectEndSuffix(prefix, suffix,
					expressionString, afterPrefixIndex);

			if (suffixIndex == -1) {
				throw new ParseException(expressionString, prefixIndex,
						"No ending suffix '" + suffix
								+ "' for expression starting at character "
								+ prefixIndex + ": "
								+ expressionString.substring(prefixIndex));
			}

			if (suffixIndex == afterPrefixIndex) {
				throw new ParseException(expressionString, prefixIndex,
						"No expression defined within delimiter '" + prefix + suffix
								+ "' at character " + prefixIndex);
			}
			// 去除前缀和后缀之后的字符串
			String expr = expressionString.substring(prefixIndex + prefix.length(),
					suffixIndex);
			// 去除前后空格
			expr = expr.trim();

			if (expr.length() == 0) {
				throw new ParseException(expressionString, prefixIndex,
						"No expression defined within delimiter '" + prefix + suffix
								+ "' at character " + prefixIndex);
			}
			// 将截取的字符串在指定的上下文中解析成表达式
			expressions.add(doParseExpression(expr, context));
			// 计算新的后缀
			startIdx = suffixIndex + suffix.length();
		}
		else {
			// 在表达式字符串中没有发现 #{expressions},则写入字面值表达式
			expressions.add(createLiteralExpression(context,
					expressionString.substring(startIdx)));
			startIdx = expressionString.length();
		}
	}
	// 返回解析成功的表达式
	return expressions.toArray(new Expression[expressions.size()]);
}

TemplateAwareExpressionParser.java

private Expression createLiteralExpression(ParserContext context, String text) {
	return new LiteralExpression(text);
}

再回到上面的evaluate方法,return expr.getValue(sec); 实际上是调用LiteralExpression的getValue方法,得到值 “10”
经过上面的解析,我们再来看看resolveTargetType方法。

BeanDefinitionValueResolver.java

protected Class<?> resolveTargetType(TypedStringValue value) throws ClassNotFoundException {
	if (value.hasTargetType()) {
		return value.getTargetType();
	}
	return value.resolveTargetType(this.beanFactory.getBeanClassLoader());
}

BeanDefinitionValueResolver.java

public Class<?> resolveTargetType(ClassLoader classLoader) throws ClassNotFoundException {
	if (this.targetType == null) {
		return null;
	}
	Class<?> resolvedClass = ClassUtils.forName(getTargetTypeName(), classLoader);
	this.targetType = resolvedClass;
	return resolvedClass;
}

没有目标类型,返回为null,我们再回到BeanDefinitionValueResolver的convertIfNecessary方法resolveTargetType,发现resolvedTargetType返回值为null,我们再次回到AbstractAutowireCapableBeanFactory的resolveValueIfNecessary方法,得到resolvedValue 的值是"10"字符串,下面,我们继续跟进
isWritablePropert方法,这个方法很重要,其中包含了score类型的获取。

在这里插入图片描述

AbstractNestablePropertyAccessor.java

@Override
public boolean isWritableProperty(String propertyName) {
	try {
		PropertyHandler ph = getPropertyHandler(propertyName);
		if (ph != null) {
			return ph.isWritable();
		}
		else {
			getPropertyValue(propertyName);
			return true;
		}
	}
	catch (InvalidPropertyException ex) {
	}
	return false;
}

AbstractNestablePropertyAccessor.java

protected PropertyHandler getPropertyHandler(String propertyName) throws BeansException {
	Assert.notNull(propertyName, "Property name must not be null");
	AbstractNestablePropertyAccessor nestedPa = getPropertyAccessorForPropertyPath(propertyName);
	return nestedPa.getLocalPropertyHandler(getFinalPath(nestedPa, propertyName));
}

AbstractNestablePropertyAccessor.java

protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath) {
	//调用这个方法的主要目标是看字符串中是不是包含点,如 user.userName 
	int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
	if (pos > -1) {
		//user.userName 
		String nestedProperty = propertyPath.substring(0, pos);
		String nestedPath = propertyPath.substring(pos + 1);
		AbstractNestablePropertyAccessor nestedPa = getNestedPropertyAccessor(nestedProperty);
		return nestedPa.getPropertyAccessorForPropertyPath(nestedPath);
	}
	else {
		return this;
	}
}

PropertyAccessorUtils.java

public static int getFirstNestedPropertySeparatorIndex(String propertyPath) {
	return getNestedPropertySeparatorIndex(propertyPath, false);
}

PropertyAccessorUtils.java

private static int getNestedPropertySeparatorIndex(String propertyPath, boolean last) {
	boolean inKey = false;
	int length = propertyPath.length();
	int i = (last ? length - 1 : 0);
	while (last ? i >= 0 : i < length) {
		switch (propertyPath.charAt(i)) {
			case '[':
			case ']':
				inKey = !inKey;
				break;
			case '.':
				if (!inKey) {
					return i;
				}
		}
		if (last) {
			i--;
		}
		else {
			i++;
		}
	}
	return -1;
}

我们回到AbstractNestablePropertyAccessor的getPropertyHandler方法

BeanWrapperImpl.java

@Override
protected BeanPropertyHandler getLocalPropertyHandler(String propertyName) {
	PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);
	if (pd != null) {
		return new BeanPropertyHandler(pd);
	}
	return null;
}

BeanWrapperImpl.java

private CachedIntrospectionResults getCachedIntrospectionResults() {
	Assert.state(getWrappedInstance() != null, "BeanWrapper does not hold a bean instance");
	if (this.cachedIntrospectionResults == null) {
		this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
	}
	return this.cachedIntrospectionResults;
}

CachedIntrospectionResults.java

static CachedIntrospectionResults forClass(Class<?> beanClass) throws BeansException {
	CachedIntrospectionResults results = strongClassCache.get(beanClass);
	if (results != null) {
		return results;
	}
	//先通过类从缓存中获取,beanClass 是student
	results = softClassCache.get(beanClass);
	if (results != null) {
		return results;
	}
	results = new CachedIntrospectionResults(beanClass);
	ConcurrentMap<Class<?>, CachedIntrospectionResults> classCacheToUse;

	if (ClassUtils.isCacheSafe(beanClass, CachedIntrospectionResults.class.getClassLoader()) ||
			isClassLoaderAccepted(beanClass.getClassLoader())) {
		classCacheToUse = strongClassCache;
	}
	else {
		if (logger.isDebugEnabled()) {
			logger.debug("Not strongly caching class [" + beanClass.getName() + "] because it is not cache-safe");
		}
		classCacheToUse = softClassCache;
	}

	CachedIntrospectionResults existing = classCacheToUse.putIfAbsent(beanClass, results);
	return (existing != null ? existing : results);
}

CachedIntrospectionResults.java

private CachedIntrospectionResults(Class<?> beanClass) throws BeansException {
	try {
		if (logger.isTraceEnabled()) {
			logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
		}

		BeanInfo beanInfo = null;
		for (BeanInfoFactory beanInfoFactory : beanInfoFactories) {
			beanInfo = beanInfoFactory.getBeanInfo(beanClass);
			if (beanInfo != null) {
				break;
			}
		}
		if (beanInfo == null) {
			// If none of the factories supported the class, fall back to the default
			beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
					Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
					Introspector.getBeanInfo(beanClass));
		}
		this.beanInfo = beanInfo;

		if (logger.isTraceEnabled()) {
			logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
		}
		this.propertyDescriptorCache = new LinkedHashMap<String, PropertyDescriptor>();

		// This call is slow so we do it once.
		PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
		for (PropertyDescriptor pd : pds) {
			if (Class.class == beanClass &&
					("classLoader".equals(pd.getName()) ||  "protectionDomain".equals(pd.getName()))) {
				// Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those
				continue;
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Found bean property '" + pd.getName() + "'" +
						(pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") +
						(pd.getPropertyEditorClass() != null ?
								"; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));
			}
			pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
			this.propertyDescriptorCache.put(pd.getName(), pd);
		}

		this.typeDescriptorCache = new ConcurrentReferenceHashMap<PropertyDescriptor, TypeDescriptor>();
	}
	catch (IntrospectionException ex) {
		throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
	}
}

CachedIntrospectionResults.java

private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class<?> beanClass, PropertyDescriptor pd) {
	try {
		return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
				pd.getWriteMethod(), pd.getPropertyEditorClass());
	}
	catch (IntrospectionException ex) {
		throw new FatalBeanException("Failed to re-introspect class [" + beanClass.getName() + "]", ex);
	}
}

GenericTypeAwarePropertyDescriptor.java

public GenericTypeAwarePropertyDescriptor(Class<?> beanClass, String propertyName,
		Method readMethod, Method writeMethod, Class<?> propertyEditorClass)
		throws IntrospectionException {
	super(propertyName, null, null);

	if (beanClass == null)  {
		throw new IntrospectionException("Bean class must not be null");
	}
	this.beanClass = beanClass;
	//检测有没有桥接方法
	Method readMethodToUse = BridgeMethodResolver.findBridgedMethod(readMethod);
	Method writeMethodToUse = BridgeMethodResolver.findBridgedMethod(writeMethod);
	if (writeMethodToUse == null && readMethodToUse != null) {
		// Fallback: Original JavaBeans introspection might not have found matching setter
		// method due to lack of bridge method resolution, in case of the getter using a
		// covariant return type whereas the setter is defined for the concrete property type.
		Method candidate = ClassUtils.getMethodIfAvailable(
				this.beanClass, "set" + StringUtils.capitalize(getName()), (Class<?>[]) null);
		if (candidate != null && candidate.getParameterTypes().length == 1) {
			writeMethodToUse = candidate;
		}
	}
	this.readMethod = readMethodToUse;
	this.writeMethod = writeMethodToUse;

	if (this.writeMethod != null) {
		//如果写方法不为空,读方法为空
		if (this.readMethod == null) {
			// Write method not matched against read method: potentially ambiguous through
			// several overloaded variants, in which case an arbitrary winner has been chosen
			// by the JDK's JavaBeans Introspector...
			Set ambiguousCandidates = new HashSet();
			for (Method method : beanClass.getMethods()) {
				if (method.getName().equals(writeMethodToUse.getName()) &&
						!method.equals(writeMethodToUse) && !method.isBridge() &&
						method.getParameterTypes().length == writeMethodToUse.getParameterTypes().length) {
					ambiguousCandidates.add(method);
				}
			}
			if (!ambiguousCandidates.isEmpty()) {
				this.ambiguousWriteMethods = ambiguousCandidates;
			}
		}
		this.writeMethodParameter = new MethodParameter(this.writeMethod, 0);
		GenericTypeResolver.resolveParameterType(this.writeMethodParameter, this.beanClass);
	}

	if (this.readMethod != null) {
		//如果get,set 方法都不为空
		this.propertyType = GenericTypeResolver.resolveReturnType(this.readMethod, this.beanClass);
	}
	else if (this.writeMethodParameter != null) {
		this.propertyType = this.writeMethodParameter.getParameterType();
	}

	this.propertyEditorClass = propertyEditorClass;
}

GenericTypeResolver.java

public static Class<?> resolveReturnType(Method method, Class<?> clazz) {
	Assert.notNull(method, "Method must not be null");
	Assert.notNull(clazz, "Class must not be null");
	return ResolvableType.forMethodReturnType(method, clazz).resolve(method.getReturnType());
}

ResolvableType.java

public static ResolvableType forMethodReturnType(Method method, Class<?> implementationClass) {
	Assert.notNull(method, "Method must not be null");
	MethodParameter methodParameter = new MethodParameter(method, -1);
	methodParameter.setContainingClass(implementationClass);
	return forMethodParameter(methodParameter);
}

public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
	return forMethodParameter(methodParameter, (Type) null);
}

public static ResolvableType forMethodParameter(MethodParameter methodParameter, Type targetType) {
	Assert.notNull(methodParameter, "MethodParameter must not be null");
	ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
	return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
			getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
}

ResolvableType.java

static ResolvableType forType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
	if (type == null && typeProvider != null) {
		type = SerializableTypeWrapper.forTypeProvider(typeProvider);
	}
	if (type == null) {
		return NONE;
	}

	// For simple Class references, build the wrapper right away -
	// no expensive resolution necessary, so not worth caching...
	if (type instanceof Class) {
		return new ResolvableType(type, typeProvider, variableResolver, null);
	}

	// Purge empty entries on access since we don't have a clean-up thread or the like.
	cache.purgeUnreferencedEntries();

	// Check the cache - we may have a ResolvableType which has been resolved before...
	ResolvableType key = new ResolvableType(type, typeProvider, variableResolver);
	ResolvableType resolvableType = cache.get(key);
	if (resolvableType == null) {
		resolvableType = new ResolvableType(type, typeProvider, variableResolver, null);
		cache.put(resolvableType, resolvableType);
	}
	return resolvableType;
}

SerializableTypeWrapper.java

static Type forTypeProvider(final TypeProvider provider) {
	Assert.notNull(provider, "Provider must not be null");
	if (provider.getType() instanceof Serializable || provider.getType() == null) {
		return provider.getType();
	}
	Type cached = cache.get(provider.getType());
	if (cached != null) {
		return cached;
	}
	for (Class<?> type : SUPPORTED_SERIALIZABLE_TYPES) {
		if (type.isAssignableFrom(provider.getType().getClass())) {
			ClassLoader classLoader = provider.getClass().getClassLoader();
			Class<?>[] interfaces = new Class<?>[] { type,
				SerializableTypeProxy.class, Serializable.class };
			InvocationHandler handler = new TypeProxyInvocationHandler(provider);
			cached = (Type) Proxy.newProxyInstance(classLoader, interfaces, handler);
			cache.put(provider.getType(), cached);
			return cached;
		}
	}
	throw new IllegalArgumentException("Unsupported Type class " + provider.getType().getClass().getName());
}

SerializableTypeWrapper.java

@Override
public Type getType() {
	return this.methodParameter.getGenericParameterType();
}

MethodParameter.java

public Type getGenericParameterType() {
	if (this.genericParameterType == null) {
		//如果是get方法
		if (this.parameterIndex < 0) {
			this.genericParameterType = (this.method != null ? this.method.getGenericReturnType() : null);
		}
		else {
			//如果是set方法
			this.genericParameterType = (this.method != null ?
				this.method.getGenericParameterTypes()[this.parameterIndex] :
				this.constructor.getGenericParameterTypes()[this.parameterIndex]);
		}
	}
	return this.genericParameterType;
}

Method.java

@Override
public Type[] getGenericParameterTypes() {
    return super.getGenericParameterTypes();
}

Executable.java

public Type[] getGenericParameterTypes() {
    if (hasGenericInformation())
        return getGenericInfo().getParameterTypes();
    else
        return getParameterTypes();
}

Method.java

@Override
public Class<?>[] getParameterTypes() {
    return parameterTypes.clone();
}

在上述方法中,先拿到BeanInfo,从BeanInfo中获取PropertyDescriptor列表,并创建属性的GenericTypeAwarePropertyDescriptor对象,在这个对象的创建过程中,获取属性的get set 方法,如果是set 方法,获取方法的第一个参数的类型,如果是get 方法,则获取方法的返回值类型,从而得到属性的Type类型,保存到GenericTypeAwarePropertyDescriptor对象的保存到propertyType属性中,再将每个属性的GenericTypeAwarePropertyDescriptor对象保存到对象的propertyDescriptorCache缓存中。

Introspector.java

public static BeanInfo getBeanInfo(Class<?> beanClass)
    throws IntrospectionException
{
    if (!ReflectUtil.isPackageAccessible(beanClass)) {
        return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
    }
    ThreadGroupContext context = ThreadGroupContext.getContext();
    BeanInfo beanInfo;
    synchronized (declaredMethodCache) {
        beanInfo = context.getBeanInfo(beanClass);
    }
    if (beanInfo == null) {
    	//在这方法中,先获取父类的beanInfo,再获取自己的beanInfo
        beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
        synchronized (declaredMethodCache) {
            context.putBeanInfo(beanClass, beanInfo);
        }
    }
    return beanInfo;
}

Introspector.java

private Introspector(Class<?> beanClass, Class<?> stopClass, int flags)
                                        throws IntrospectionException {
    this.beanClass = beanClass;

    // Check stopClass is a superClass of startClass.
    if (stopClass != null) {
        boolean isSuper = false;
        for (Class<?> c = beanClass.getSuperclass(); c != null; c = c.getSuperclass()) {
            if (c == stopClass) {
                isSuper = true;
            }
        }
        if (!isSuper) {
            throw new IntrospectionException(stopClass.getName() + " not superclass of " +
                                    beanClass.getName());
        }
    }

    if (flags == USE_ALL_BEANINFO) {
        explicitBeanInfo = findExplicitBeanInfo(beanClass);
    }

    Class<?> superClass = beanClass.getSuperclass();
    if (superClass != stopClass) {
        int newFlags = flags;
        if (newFlags == IGNORE_IMMEDIATE_BEANINFO) {
            newFlags = USE_ALL_BEANINFO;
        }
        //先获取父类的beanInfo
        superBeanInfo = getBeanInfo(superClass, stopClass, newFlags);
    }
    if (explicitBeanInfo != null) {
        additionalBeanInfo = explicitBeanInfo.getAdditionalBeanInfo();
    }
    if (additionalBeanInfo == null) {
        additionalBeanInfo = new BeanInfo[0];
    }
}

public static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass,
                                    int flags) throws IntrospectionException {
    BeanInfo bi;
    if (stopClass == null && flags == USE_ALL_BEANINFO) {
        bi = getBeanInfo(beanClass);
    } else {
        bi = (new Introspector(beanClass, stopClass, flags)).getBeanInfo();
    }
    return bi;
}

Introspector.java

private BeanInfo getBeanInfo() throws IntrospectionException {
	//获取student类的描述器
    BeanDescriptor bd = getTargetBeanDescriptor();
    MethodDescriptor mds[] = getTargetMethodInfo();
    EventSetDescriptor esds[] = getTargetEventInfo();
    PropertyDescriptor pds[] = getTargetPropertyInfo();

    int defaultEvent = getTargetDefaultEventIndex();
    int defaultProperty = getTargetDefaultPropertyIndex();
    return new GenericBeanInfo(bd, esds, defaultEvent, pds,
                    defaultProperty, mds, explicitBeanInfo);

}

Introspector.java

private MethodDescriptor[] getTargetMethodInfo() {
    if (methods == null) {
        methods = new HashMap<>(100);
    }

    // Check if the bean has its own BeanInfo that will provide
    // explicit information.
    MethodDescriptor[] explicitMethods = null;
    if (explicitBeanInfo != null) {
        explicitMethods = explicitBeanInfo.getMethodDescriptors();
    }

    if (explicitMethods == null && superBeanInfo != null) {
        // We have no explicit BeanInfo methods.  Check with our parent.
        将所有的父类方法保存起来
        MethodDescriptor supers[] = superBeanInfo.getMethodDescriptors();
        for (int i = 0 ; i < supers.length; i++) {
            addMethod(supers[i]);
        }
    }

    for (int i = 0; i < additionalBeanInfo.length; i++) {
        MethodDescriptor additional[] = additionalBeanInfo[i].getMethodDescriptors();
        if (additional != null) {
            for (int j = 0 ; j < additional.length; j++) {
                addMethod(additional[j]);
            }
        }
    }

    if (explicitMethods != null) {
        // Add the explicit explicitBeanInfo data to our results.
        for (int i = 0 ; i < explicitMethods.length; i++) {
            addMethod(explicitMethods[i]);
        }

    } else {

        // Apply some reflection to the current class.

        // First get an array of all the beans methods at this level
        //过滤一些static,非public方法
        Method methodList[] = getPublicDeclaredMethods(beanClass);

        // Now analyze each method.
        for (int i = 0; i < methodList.length; i++) {
            Method method = methodList[i];
            if (method == null) {
                continue;
            }
            //将子类方法和父类方法合并
            MethodDescriptor md = new MethodDescriptor(method);
            addMethod(md);
        }
    }

    // Allocate and populate the result array.
    MethodDescriptor result[] = new MethodDescriptor[methods.size()];
    result = methods.values().toArray(result);

    return result;
}

Introspector.java

private void addMethod(MethodDescriptor md) {
    String name = md.getName();
    //看方法中是不是存在此类方法名称描述器
    MethodDescriptor old = methods.get(name);
    if (old == null) {
    	//如果不存在,直接加入到methods
        methods.put(name, md);
        return;
    }

    String[] p1 = md.getParamNames();
    String[] p2 = old.getParamNames();
	
    boolean match = false;
    //如果方法中参数名称个数相等,并且参数类型名字相同
    if (p1.length == p2.length) {
        match = true;
        for (int i = 0; i < p1.length; i++) {
            if (p1[i] != p2[i]) {
                match = false;
                break;
            }
        }
    }
    if (match) {
    	//如果匹配,则合并方法,构建复杂方法
        MethodDescriptor composite = new MethodDescriptor(old, md);
        methods.put(name, composite);
        return;
    }
    //返回方法名称=:参数类型:参数类型...,如wait=:long:int
    String longKey = makeQualifiedMethodName(name, p1);
    old = methods.get(longKey);
    //如果复杂方法名称己经存在,则构建复杂方法名,如果不存在,直接保存
    if (old == null) {
        methods.put(longKey, md);
        return;
    }
    MethodDescriptor composite = new MethodDescriptor(old, md);
    methods.put(longKey, composite);
}

Introspector.java

private static Method[] getPublicDeclaredMethods(Class<?> clz) {
    // Looking up Class.getDeclaredMethods is relatively expensive,
    // so we cache the results.
    if (!ReflectUtil.isPackageAccessible(clz)) {
        return new Method[0];
    }
    synchronized (declaredMethodCache) {
        Method[] result = declaredMethodCache.get(clz);
        if (result == null) {
            result = clz.getMethods();
            for (int i = 0; i < result.length; i++) {
                Method method = result[i];
                //忽略掉父类的方法
                if (!method.getDeclaringClass().equals(clz)) {
                    result[i] = null; // ignore methods declared elsewhere
                }
                else {
                    try {
                    	//在这个方法中,过滤掉一些非public方法,static方法等
                        method = MethodFinder.findAccessibleMethod(method);
                        Class<?> type = method.getDeclaringClass();
                        result[i] = type.equals(clz) || type.isInterface()
                                ? method
                                : null; 
                    }
                    catch (NoSuchMethodException exception) {
                        // commented out because of 6976577
                        // result[i] = null; // ignore inaccessible methods
                    }
                }
            }
            declaredMethodCache.put(clz, result);
        }
        return result;
    }
}

Introspector.java

private PropertyDescriptor[] getTargetPropertyInfo() {

    PropertyDescriptor[] explicitProperties = null;
    if (explicitBeanInfo != null) {
        explicitProperties = getPropertyDescriptors(this.explicitBeanInfo);
    }

    if (explicitProperties == null && superBeanInfo != null) {
        addPropertyDescriptors(getPropertyDescriptors(this.superBeanInfo));
    }

    for (int i = 0; i < additionalBeanInfo.length; i++) {
        addPropertyDescriptors(additionalBeanInfo[i].getPropertyDescriptors());
    }

    if (explicitProperties != null) {
        // Add the explicit BeanInfo data to our results.
        addPropertyDescriptors(explicitProperties);

    } else {

        // Apply some reflection to the current class.

        // 获取到所有的公有的方法
        Method methodList[] = getPublicDeclaredMethods(beanClass);

        // Now analyze each method.
        for (int i = 0; i < methodList.length; i++) {
            Method method = methodList[i];
            if (method == null) {
                continue;
            }
            // skip static methods.
            int mods = method.getModifiers();
            if (Modifier.isStatic(mods)) {
                continue;
            }
            String name = method.getName();
            Class<?>[] argTypes = method.getParameterTypes();
            Class<?> resultType = method.getReturnType();
            int argCount = argTypes.length;
            PropertyDescriptor pd = null;

            if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) {
                // Optimization. Don't bother with invalid propertyNames.
                continue;
            }

            try {

                if (argCount == 0) {
                    if (name.startsWith(GET_PREFIX)) {
                        //获取所有的getter方法
                        pd = new PropertyDescriptor(this.beanClass, name.substring(3), method, null);
                    } else if (resultType == boolean.class && name.startsWith(IS_PREFIX)) {
                        // Boolean getter
                        pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null);
                    }
                } else if (argCount == 1) {
                    if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
                        pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
                    } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
                        // 获取所有的set方法
                        pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
                        if (throwsException(method, PropertyVetoException.class)) {
                            pd.setConstrained(true);
                        }
                    }
                } else if (argCount == 2) {
                        if (void.class.equals(resultType) && int.class.equals(argTypes[0]) && name.startsWith(SET_PREFIX)) {
                        pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method);
                        if (throwsException(method, PropertyVetoException.class)) {
                            pd.setConstrained(true);
                        }
                    }
                }
            } catch (IntrospectionException ex) {
                // This happens if a PropertyDescriptor or IndexedPropertyDescriptor
                // constructor fins that the method violates details of the deisgn
                // pattern, e.g. by having an empty name, or a getter returning
                // void , or whatever.
                pd = null;
            }

            if (pd != null) {
                // If this class or one of its base classes is a PropertyChange
                // source, then we assume that any properties we discover are "bound".
                if (propertyChangeSource) {
                    pd.setBound(true);
                }
                addPropertyDescriptor(pd);
            }
        }
    }
     //合并get set 方法,内部实现非常的复杂,这里有兴趣的小伙伴可以自行打断点研究一下
    processPropertyDescriptors();

    // Allocate and populate the result array.
    PropertyDescriptor result[] =
            properties.values().toArray(new PropertyDescriptor[properties.size()]);

    // Set the default index.
    if (defaultPropertyName != null) {
        for (int i = 0; i < result.length; i++) {
            if (defaultPropertyName.equals(result[i].getName())) {
                defaultPropertyIndex = i;
            }
        }
    }

    return result;
}

分析到这里,我们终于看到的久违的署光,终于得到了beanInfo信息。
在这里插入图片描述

通过上面的分析,我们得到了BeanInfo,再通过getPropertyDescriptor获取PropertyDescriptor,

CachedIntrospectionResults.java

PropertyDescriptor getPropertyDescriptor(String name) {
	PropertyDescriptor pd = this.propertyDescriptorCache.get(name);
	if (pd == null && StringUtils.hasLength(name)) {
		// Same lenient fallback checking as in PropertyTypeDescriptor...

		pd = this.propertyDescriptorCache.get(name.substring(0, 1).toLowerCase() + name.substring(1));
		if (pd == null) {
			pd = this.propertyDescriptorCache.get(name.substring(0, 1).toUpperCase() + name.substring(1));
		}
	}
	return (pd == null || pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
			buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
}

在这里插入图片描述
我们终于从propertyDescriptorCache中拿到了score的PropertyDescriptor
那我们回到前面的AbstractAutowireCapableBeanFactory的convertForProperty方法

AbstractAutowireCapableBeanFactory.java

private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
	if (converter instanceof BeanWrapperImpl) {
		return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
	}
	else {
		PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
		MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
		return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
	}
}

BeanWrapperImpl.java

public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException {
	CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
	PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
	if (pd == null) {
		throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,
				"No property '" + propertyName + "' found");
	}
	//从缓存中获取TypeDescriptor
	TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
	if (td == null) {
		//构建TypeDescriptor
		td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd)));
	}
	return convertForProperty(propertyName, null, value, td);
}

BeanWrapperImpl.java

private Property property(PropertyDescriptor pd) {
	GenericTypeAwarePropertyDescriptor gpd = (GenericTypeAwarePropertyDescriptor) pd;
	return new Property(gpd.getBeanClass(), gpd.getReadMethod(), gpd.getWriteMethod(), gpd.getName());
}

Property.java

public Property(Class<?> objectType, Method readMethod, Method writeMethod, String name) {
	this.objectType = objectType;
	this.readMethod = readMethod;
	this.writeMethod = writeMethod;
	this.methodParameter = resolveMethodParameter();
	this.name = (name == null ? resolveName() : name);
}

Property.java

private MethodParameter resolveMethodParameter() {
	MethodParameter read = resolveReadMethodParameter();
	MethodParameter write = resolveWriteMethodParameter();
	if (write == null) {
		if (read == null) {
			throw new IllegalStateException("Property is neither readable nor writeable");
		}
		return read;
	}
	if (read != null) {
		Class<?> readType = read.getParameterType();
		Class<?> writeType = write.getParameterType();
		if (!writeType.equals(readType) && writeType.isAssignableFrom(readType)) {
			return read;
		}
	}
	return write;
}

Property.java

private MethodParameter resolveWriteMethodParameter() {
	if (getWriteMethod() == null) {
		return null;
	}
	return resolveParameterType(new MethodParameter(getWriteMethod(), 0));
}

private MethodParameter resolveParameterType(MethodParameter parameter) {
	// needed to resolve generic property types that parameterized by sub-classes e.g. T getFoo();
	GenericTypeResolver.resolveParameterType(parameter, getObjectType());
	return parameter;
}

GenericTypeResolver.java

public static Class<?> resolveParameterType(MethodParameter methodParam, Class<?> clazz) {
	Assert.notNull(methodParam, "MethodParameter must not be null");
	Assert.notNull(clazz, "Class must not be null");
	methodParam.setContainingClass(clazz);
	methodParam.setParameterType(ResolvableType.forMethodParameter(methodParam).resolve());
	return methodParam.getParameterType();
}

ResolvableType.java

public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
	return forMethodParameter(methodParameter, (Type) null);
}

ResolvableType.java

public static ResolvableType forMethodParameter(MethodParameter methodParameter, Type targetType) {
	Assert.notNull(methodParameter, "MethodParameter must not be null");
	ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
	//这里我们又回到了上面的获取ResolvableType的方法步骤
	return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
			getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
}

我们这里终于通过resolveParameterType方法将方法将MethodParameter对象填充并返回给methodParameter实体属性,而在new TypeDescriptor()时,将Type存入到TypeTypeDescriptor中,如下

TypeDescriptor.java

public TypeDescriptor(Property property) {
	Assert.notNull(property, "Property must not be null");
	this.resolvableType = ResolvableType.forMethodParameter(property.getMethodParameter());
	//其实这里也只是通过调用属性的get set 方法,的返回类型或者第一个参数类型来获取属性的类型,明显score属性
	// 其参数类型是int,而user的类型是User 
	this.type = this.resolvableType.resolve(property.getType());
	this.annotations = nullSafeAnnotations(property.getAnnotations());
}

经过上面一系列的繁琐的解析,终于得到了score的类型是int 类型,那么下面,我们来进行参数转换。将字符串"10"转换成int 类型的10 。

BeanWrapperImpl.java

protected Object convertForProperty(String propertyName, Object oldValue, Object newValue, TypeDescriptor td)
		throws TypeMismatchException {

	return convertIfNecessary(propertyName, oldValue, newValue, td.getType(), td);
}

AbstractNestablePropertyAccessor.java

private Object convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<?> requiredType,
		TypeDescriptor td) throws TypeMismatchException {
	try {
		// this.typeConverterDelegate默认值是TypeConverterDelegate对象
		return this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);
	}
	catch (ConverterNotFoundException ex) {
		PropertyChangeEvent pce =
				new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
		throw new ConversionNotSupportedException(pce, td.getType(), ex);
	}
	catch (ConversionException ex) {
		PropertyChangeEvent pce =
				new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
		throw new TypeMismatchException(pce, requiredType, ex);
	}
	catch (IllegalStateException ex) {
		PropertyChangeEvent pce =
				new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
		throw new ConversionNotSupportedException(pce, requiredType, ex);
	}
	catch (IllegalArgumentException ex) {
		PropertyChangeEvent pce =
				new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
		throw new TypeMismatchException(pce, requiredType, ex);
	}
}

TypeConverterDelegate.java

public  T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
		Class requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {

	// Custom editor for this type?
	PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

	ConversionFailedException conversionAttemptEx = null;

	// No custom editor but custom ConversionService specified?
	ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
	if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
		TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
		if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
			try {
				return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
			}
			catch (ConversionFailedException ex) {
				// fallback to default conversion logic below
				conversionAttemptEx = ex;
			}
		}
	}

	Object convertedValue = newValue;

	// Value not of required type?
	if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
		if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
			TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
			if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {
				convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
			}
		}
		if (editor == null) {
			editor = findDefaultEditor(requiredType);
		}
		convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
	}

	boolean standardConversion = false;

	if (requiredType != null) {
		// Try to apply some standard type conversion rules if appropriate.

		if (convertedValue != null) {
			if (Object.class == requiredType) {
				return (T) convertedValue;
			}
			else if (requiredType.isArray()) {
				// Array required -> apply appropriate conversion of elements.
				if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
					convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
				}
				return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
			}
			else if (convertedValue instanceof Collection) {
				// Convert elements to target type, if determined.
				convertedValue = convertToTypedCollection(
						(Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
				standardConversion = true;
			}
			else if (convertedValue instanceof Map) {
				// Convert keys and values to respective target type, if determined.
				convertedValue = convertToTypedMap(
						(Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
				standardConversion = true;
			}
			if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
				convertedValue = Array.get(convertedValue, 0);
				standardConversion = true;
			}
			if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
				// We can stringify any primitive value...
				return (T) convertedValue.toString();
			}
			else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
				if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
					try {
						Constructor strCtor = requiredType.getConstructor(String.class);
						return BeanUtils.instantiateClass(strCtor, convertedValue);
					}
					catch (NoSuchMethodException ex) {
						// proceed with field lookup
						if (logger.isTraceEnabled()) {
							logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
						}
					}
					catch (Exception ex) {
						if (logger.isDebugEnabled()) {
							logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);
						}
					}
				}
				String trimmedValue = ((String) convertedValue).trim();
				if (requiredType.isEnum() && "".equals(trimmedValue)) {
					// It's an empty enum identifier: reset the enum value to null.
					return null;
				}
				convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
				standardConversion = true;
			}
			else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
				convertedValue = NumberUtils.convertNumberToTargetClass(
						(Number) convertedValue, (Class) requiredType);
				standardConversion = true;
			}
		}
		else {
			// convertedValue == null
			if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
				convertedValue = javaUtilOptionalEmpty;
			}
		}

		if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
			if (conversionAttemptEx != null) {
				// Original exception from former ConversionService call above...
				throw conversionAttemptEx;
			}
			else if (conversionService != null) {
				// ConversionService not tried before, probably custom editor found
				// but editor couldn't produce the required type...
				TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
				if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
					return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
				}
			}

			// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
			StringBuilder msg = new StringBuilder();
			msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));
			msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");
			if (propertyName != null) {
				msg.append(" for property '").append(propertyName).append("'");
			}
			if (editor != null) {
				msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
						"] returned inappropriate value of type [").append(
						ClassUtils.getDescriptiveType(convertedValue)).append("]");
				throw new IllegalArgumentException(msg.toString());
			}
			else {
				msg.append(": no matching editors or conversion strategy found");
				throw new IllegalStateException(msg.toString());
			}
		}
	}

	if (conversionAttemptEx != null) {
		if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
			throw conversionAttemptEx;
		}
		logger.debug("Original ConversionService attempt failed - ignored since " +
				"PropertyEditor based conversion eventually succeeded", conversionAttemptEx);
	}

	return (T) convertedValue;
}

PropertyEditorRegistrySupport.java

@Override
public PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath) {
	Class<?> requiredTypeToUse = requiredType;
	if (propertyPath != null) {
		if (this.customEditorsForPath != null) {
			// Check property-specific editor first.
			PropertyEditor editor = getCustomEditor(propertyPath, requiredType);
			if (editor == null) {
				List strippedPaths = new LinkedList();
				addStrippedPropertyPaths(strippedPaths, "", propertyPath);
				for (Iterator it = strippedPaths.iterator(); it.hasNext() && editor == null;) {
					String strippedPath = it.next();
					editor = getCustomEditor(strippedPath, requiredType);
				}
			}
			if (editor != null) {
				return editor;
			}
		}
		if (requiredType == null) {
			requiredTypeToUse = getPropertyType(propertyPath);
		}
	}
	// No property-specific editor -> check type-specific editor.
	return getCustomEditor(requiredTypeToUse);
}

PropertyEditorRegistrySupport.java

private PropertyEditor getCustomEditor(Class<?> requiredType) {
	if (requiredType == null || this.customEditors == null) {
		return null;
	}
	// Check directly registered editor for type.
	PropertyEditor editor = this.customEditors.get(requiredType);
	if (editor == null) {
		// Check cached editor for type, registered for superclass or interface.
		if (this.customEditorCache != null) {
			editor = this.customEditorCache.get(requiredType);
		}
		if (editor == null) {
			// Find editor for superclass or interface.
			for (Iterator<Class<?>> it = this.customEditors.keySet().iterator(); it.hasNext() && editor == null;) {
				Class<?> key = it.next();
				if (key.isAssignableFrom(requiredType)) {
					editor = this.customEditors.get(key);
					// Cache editor for search type, to avoid the overhead
					// of repeated assignable-from checks.
					if (this.customEditorCache == null) {
						this.customEditorCache = new HashMap<Class<?>, PropertyEditor>();
					}
					this.customEditorCache.put(requiredType, editor);
				}
			}
		}
	}
	return editor;
}

TypeConverterDelegate.java

private PropertyEditor findDefaultEditor(Class<?> requiredType) {
	PropertyEditor editor = null;
	if (requiredType != null) {
		// No custom editor -> check BeanWrapperImpl's default editors.
		editor = this.propertyEditorRegistry.getDefaultEditor(requiredType);
		if (editor == null && String.class != requiredType) {
			// No BeanWrapper default editor -> check standard JavaBean editor.
			editor = BeanUtils.findEditorByConvention(requiredType);
		}
	}
	return editor;
}

PropertyEditorRegistrySupport.java

public PropertyEditor getDefaultEditor(Class<?> requiredType) {
	if (!this.defaultEditorsActive) {
		return null;
	}
	if (this.overriddenDefaultEditors != null) {
		//先从继承过来的属性编辑器中获取属性转换器
		PropertyEditor editor = this.overriddenDefaultEditors.get(requiredType);
		if (editor != null) {
			return editor;
		}
	}
	if (this.defaultEditors == null) {
		//如果没有,则直接从默认的属性转换器中加载并获取
		createDefaultEditors();
	}
	return this.defaultEditors.get(requiredType);
}

PropertyEditorRegistrySupport.java

private void createDefaultEditors() {
	this.defaultEditors = new HashMap<Class<?>, PropertyEditor>(64);

	// Simple editors, without parameterization capabilities.
	// The JDK does not contain a default editor for any of these target types.
	this.defaultEditors.put(Charset.class, new CharsetEditor());
	this.defaultEditors.put(Class.class, new ClassEditor());
	this.defaultEditors.put(Class[].class, new ClassArrayEditor());
	this.defaultEditors.put(Currency.class, new CurrencyEditor());
	this.defaultEditors.put(File.class, new FileEditor());
	this.defaultEditors.put(InputStream.class, new InputStreamEditor());
	this.defaultEditors.put(InputSource.class, new InputSourceEditor());
	this.defaultEditors.put(Locale.class, new LocaleEditor());
	this.defaultEditors.put(Pattern.class, new PatternEditor());
	this.defaultEditors.put(Properties.class, new PropertiesEditor());
	this.defaultEditors.put(Reader.class, new ReaderEditor());
	this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
	this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
	this.defaultEditors.put(URI.class, new URIEditor());
	this.defaultEditors.put(URL.class, new URLEditor());
	this.defaultEditors.put(UUID.class, new UUIDEditor());
	if (zoneIdClass != null) {
		this.defaultEditors.put(zoneIdClass, new ZoneIdEditor());
	}

	// Default instances of collection editors.
	// Can be overridden by registering custom instances of those as custom editors.
	this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
	this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
	this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
	this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
	this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));

	// Default editors for primitive arrays.
	this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
	this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());

	// The JDK does not contain a default editor for char!
	this.defaultEditors.put(char.class, new CharacterEditor(false));
	this.defaultEditors.put(Character.class, new CharacterEditor(true));

	// Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
	this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
	this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));

	// The JDK does not contain default editors for number wrapper types!
	// Override JDK primitive number editors with our own CustomNumberEditor.
	this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
	this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
	this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
	this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
	this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
	this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
	this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
	this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
	this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
	this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
	this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
	this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
	this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
	this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));

	// Only register config value editors if explicitly requested.
	if (this.configValueEditorsActive) {
		StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
		this.defaultEditors.put(String[].class, sae);
		this.defaultEditors.put(short[].class, sae);
		this.defaultEditors.put(int[].class, sae);
		this.defaultEditors.put(long[].class, sae);
	}
}

在这里插入图片描述

加载完成后,肯定有int类型的转换器。

private Object doConvertValue(Object oldValue, Object newValue, Class<?> requiredType, PropertyEditor editor) {
	Object convertedValue = newValue;

	if (editor != null && !(convertedValue instanceof String)) {
		// Not a String -> use PropertyEditor's setValue.
		// With standard PropertyEditors, this will return the very same object;
		// we just want to allow special PropertyEditors to override setValue
		// for type conversion from non-String values to the required type.
		try {
			editor.setValue(convertedValue);
			Object newConvertedValue = editor.getValue();
			if (newConvertedValue != convertedValue) {
				convertedValue = newConvertedValue;
				// Reset PropertyEditor: It already did a proper conversion.
				// Don't use it again for a setAsText call.
				editor = null;
			}
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
			}
			// Swallow and proceed.
		}
	}

	Object returnValue = convertedValue;

	if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
		// Convert String array to a comma-separated String.
		// Only applies if no PropertyEditor converted the String array before.
		// The CSV String will be passed into a PropertyEditor's setAsText method, if any.
		if (logger.isTraceEnabled()) {
			logger.trace("Converting String array to comma-delimited String [" + convertedValue + "]");
		}
		convertedValue = StringUtils.arrayToCommaDelimitedString((String[]) convertedValue);
	}

	if (convertedValue instanceof String) {
		if (editor != null) {
			// Use PropertyEditor's setAsText in case of a String value.
			if (logger.isTraceEnabled()) {
				logger.trace("Converting String to [" + requiredType + "] using property editor [" + editor + "]");
			}
			String newTextValue = (String) convertedValue;
			return doConvertTextValue(oldValue, newTextValue, editor);
		}
		else if (String.class == requiredType) {
			returnValue = convertedValue;
		}
	}

	return returnValue;
}

TypeConverterDelegate.java

private Object doConvertTextValue(Object oldValue, String newTextValue, PropertyEditor editor) {
	try {
		editor.setValue(oldValue);
	}
	catch (Exception ex) {
		if (logger.isDebugEnabled()) {
			logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
		}
		// Swallow and proceed.
	}
	editor.setAsText(newTextValue);
	return editor.getValue();
}

CustomNumberEditor.java

public void setAsText(String text) throws IllegalArgumentException {
	if (this.allowEmpty && !StringUtils.hasText(text)) {
		// Treat empty String as null value.
		setValue(null);
	}
	else if (this.numberFormat != null) {
		// Use given NumberFormat for parsing text.
		setValue(NumberUtils.parseNumber(text, this.numberClass, this.numberFormat));
	}
	else {
		// Use default valueOf methods for parsing text.
		setValue(NumberUtils.parseNumber(text, this.numberClass));
	}
}

将"10"字符串转换成我们需要的类型10,到这里我们己经完成了score的值获取,下面我们来看看user对象的值转换及获取。因为在https://blog.csdn.net/quyixiao/article/details/108654334 博客中己经写了三篇关于表达式的解析及值的获取方式,这里只是对#{user}的值的 解析方式进行分析,分词用吃掉表达式的详细情况,还需要读者自己去打断点调试吧。

SpelExpression.java

@Override
public Object getValue(EvaluationContext context) throws EvaluationException {
	Assert.notNull(context, "EvaluationContext is required");
	if (compiledAst!= null) {
		try {
			TypedValue contextRoot = context == null ? null : context.getRootObject();
			return this.compiledAst.getValue(contextRoot != null ? contextRoot.getValue() : null, context);
		}
		catch (Throwable ex) {
			// If running in mixed mode, revert to interpreted
			if (this.configuration.getCompilerMode() == SpelCompilerMode.MIXED) {
				this.interpretedCount = 0;
				this.compiledAst = null;
			}
			else {
				// Running in SpelCompilerMode.immediate mode - propagate exception to caller
				throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION);
			}
		}
	}
	ExpressionState expressionState = new ExpressionState(context, this.configuration);
	Object result = this.ast.getValue(expressionState);
	checkCompile(expressionState);
	return result;
}

SpelNodeImpl.java

@Override
public final Object getValue(ExpressionState expressionState) throws EvaluationException {
	if (expressionState != null) {
		return getValueInternal(expressionState).getValue();
	}
	else {
		// configuration not set - does that matter?
		return getValue(new ExpressionState(new StandardEvaluationContext()));
	}
}

PropertyOrFieldReference.java

@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
	TypedValue tv = getValueInternal(state.getActiveContextObject(), state.getEvaluationContext(),
			state.getConfiguration().isAutoGrowNullReferences());
	PropertyAccessor accessorToUse = this.cachedReadAccessor;
	if (accessorToUse instanceof CompilablePropertyAccessor) {
		CompilablePropertyAccessor accessor = (CompilablePropertyAccessor) accessorToUse;
		this.exitTypeDescriptor = CodeFlow.toDescriptor(accessor.getPropertyType());
	}
	return tv;
}

PropertyOrFieldReference.java

private TypedValue getValueInternal(TypedValue contextObject, EvaluationContext evalContext,
		boolean isAutoGrowNullReferences) throws EvaluationException {

	TypedValue result = readProperty(contextObject, evalContext, this.name);

	// Dynamically create the objects if the user has requested that optional behavior
	if (result.getValue() == null && isAutoGrowNullReferences &&
			nextChildIs(Indexer.class, PropertyOrFieldReference.class)) {
		TypeDescriptor resultDescriptor = result.getTypeDescriptor();
		// Create a new collection or map ready for the indexer
		if (List.class == resultDescriptor.getType()) {
			try {
				if (isWritableProperty(this.name, contextObject, evalContext)) {
					List<?> newList = ArrayList.class.newInstance();
					writeProperty(contextObject, evalContext, this.name, newList);
					result = readProperty(contextObject, evalContext, this.name);
				}
			}
			catch (InstantiationException ex) {
				throw new SpelEvaluationException(getStartPosition(), ex,
						SpelMessage.UNABLE_TO_CREATE_LIST_FOR_INDEXING);
			}
			catch (IllegalAccessException ex) {
				throw new SpelEvaluationException(getStartPosition(), ex,
						SpelMessage.UNABLE_TO_CREATE_LIST_FOR_INDEXING);
			}
		}
		else if (Map.class == resultDescriptor.getType()) {
			try {
				if (isWritableProperty(this.name,contextObject, evalContext)) {
					Map<?,?> newMap = HashMap.class.newInstance();
					writeProperty(contextObject, evalContext, this.name, newMap);
					result = readProperty(contextObject, evalContext, this.name);
				}
			}
			catch (InstantiationException ex) {
				throw new SpelEvaluationException(getStartPosition(), ex,
						SpelMessage.UNABLE_TO_CREATE_MAP_FOR_INDEXING);
			}
			catch (IllegalAccessException ex) {
				throw new SpelEvaluationException(getStartPosition(), ex,
						SpelMessage.UNABLE_TO_CREATE_MAP_FOR_INDEXING);
			}
		}
		else {
			// 'simple' object
			try {
				if (isWritableProperty(this.name,contextObject, evalContext)) {
					Object newObject  = result.getTypeDescriptor().getType().newInstance();
					writeProperty(contextObject, evalContext, this.name, newObject);
					result = readProperty(contextObject, evalContext, this.name);
				}
			}
			catch (InstantiationException ex) {
				throw new SpelEvaluationException(getStartPosition(), ex,
						SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
			}
			catch (IllegalAccessException ex) {
				throw new SpelEvaluationException(getStartPosition(), ex,
						SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
			}
		}
	}
	return result;
}

PropertyOrFieldReference.java

private TypedValue readProperty(TypedValue contextObject, EvaluationContext evalContext, String name)
		throws EvaluationException {

	Object targetObject = contextObject.getValue();
	if (targetObject == null && this.nullSafe) {
		return TypedValue.NULL;
	}

	PropertyAccessor accessorToUse = this.cachedReadAccessor;
	if (accessorToUse != null) {
		try {
			return accessorToUse.read(evalContext, contextObject.getValue(), name);
		}
		catch (Exception ex) {
			// This is OK - it may have gone stale due to a class change,
			// let's try to get a new one and call it before giving up...
			this.cachedReadAccessor = null;
		}
	}

	List accessorsToTry =
			getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
	// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
	// get the accessor and use it. If they are not cacheable but report they can read the property
	// then ask them to read it
	if (accessorsToTry != null) {
		try {
			for (PropertyAccessor accessor : accessorsToTry) {
				if (accessor.canRead(evalContext, contextObject.getValue(), name)) {
					if (accessor instanceof ReflectivePropertyAccessor) {
						accessor = ((ReflectivePropertyAccessor) accessor).createOptimalAccessor(
								evalContext, contextObject.getValue(), name);
					}
					this.cachedReadAccessor = accessor;
					return accessor.read(evalContext, contextObject.getValue(), name);
				}
			}
		}
		catch (Exception ex) {
			throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_DURING_PROPERTY_READ, name, ex.getMessage());
		}
	}
	if (contextObject.getValue() == null) {
		throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name);
	}
	else {
		throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name,
				FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
	}
}
private List getPropertyAccessorsToTry(Object contextObject, List propertyAccessors) {
	Class<?> targetType = (contextObject != null ? contextObject.getClass() : null);

	List specificAccessors = new ArrayList();
	List generalAccessors = new ArrayList();
	for (PropertyAccessor resolver : propertyAccessors) {
		Class<?>[] targets = resolver.getSpecificTargetClasses();
		if (targets == null) {
			// generic resolver that says it can be used for any type
			generalAccessors.add(resolver);
		}
		else if (targetType != null) {
			for (Class<?> clazz : targets) {
				if (clazz == targetType) {
					specificAccessors.add(resolver);
					break;
				}
				else if (clazz.isAssignableFrom(targetType)) {
					generalAccessors.add(resolver);
				}
			}
		}
	}
	List resolvers = new ArrayList();
	resolvers.addAll(specificAccessors);
	generalAccessors.removeAll(specificAccessors);
	resolvers.addAll(generalAccessors);
	return resolvers;
}

在这里插入图片描述
在这个方法中遍历所有的处理器,而这些处理器则是从evaluate方法中初始化而来。而在上面的方法中contextObject则是从 evaluateBeanDefinitionString的new BeanExpressionContext(this, scope)) 而来。
在这里,我们终于拿到了属性接收器
在这里插入图片描述
调用属性接收器的read方法

BeanExpressionContextAccessor.java

@Override
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
	return new TypedValue(((BeanExpressionContext) target).getObject(name));
}

BeanExpressionContext.java

public Object getObject(String key) {
	if (this.beanFactory.containsBean(key)) {
		return this.beanFactory.getBean(key);
	}
	else if (this.scope != null){
		return this.scope.resolveContextualObject(key);
	}
	else {
		return null;
	}
}

到这里,我们终于从beanFactory中获得了我们想要的对象User 。
在这里插入图片描述

到这里,我们终于完成了score 属性和#{user}对象的解析和获取,下面我们来总结一下。
1.首先bean的实例封装在refresh()方法的finishBeanFactoryInitialization()初始化所有剩余的单例Bean的方法中。
2.bean创建过程遍历所有的属性,进行解析赋值操作。
3.遍历bean的所有的get ,set 方法获取属性的类型。
4.从属性转换器中获取到属性类型对应的属性转换器。
5.进行属性转换。

可能一个很小的数值转换在Spring中都使用大量的代码来完成操作,因此,如果想彻底理解Spring源码是如何进行属性填充和转换的,还是建义读者多去调试代码。才能真正的理解Spring源码的执行流程。

本文的github地址是
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_101_200/test_111_120/test_113_conversion

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值