---
title: Spring源码系列-第1章-Spring源码纵览
tags:
- Spring源码
categories:
- Spring
- 源码V1
keywords: Spring,框架,Spring源码
description: Spring源码纵览
cover: 'https://npm.elemecdn.com/lql_static@latest/logo/spring.png'
abbrlink: 599156d
date: 2021-12-06 23:21:58
---
# 必读
1. 源码是循循渐进的,前面我会省略中间很多目前不需要深入的代码,所以会看起来代码比较少。省略的地方我会打上这样的标识
```java
// ...
或者
// ......
```
2. 如果没打也不代表我没省略,可能是忘记了,不要看懵了。
# 第1章-Spring源码纵览
## 概述
Spring源码纵览这一节,主要是先了解下Spring的一些核心东西,所以前后可能关联不是特别深,跳跃性比较大,往后看就行。
## 简单的继承关系图
- **蓝色实线箭头**是指继承关系
- **绿色虚线箭头**是指接口实现关系
- **绿色虚线箭头**是指接口继承关系
- 注解版使用AnnotationConfigApplicationContext
- XML版使用ClassPathXmlApplicationContext
## Spring框架整体流程
1. 不管是用XML还是注解也好,最终形成一份组件或者功能的配置清单。
2. Spring用Resource来表示所有的资源
3. 这些资源被ResourceLoader加载然后交给BeanDefinitionReader解析成BeanDefinition(Bean的定义信息)。BeanDefinition就是一个对象的图纸,模板。
4. 然后将这些BeanDefinition放入到BeanDefinitionRegistry(其实就是一个Map)里,等待以后使用。
5. 最后经过漫长的过程,根据BeanDefinition创建一个个的对象。
## 核心组件接口分析
**基础接口**
```java
Resource+ResourceLoader
BeanFactory
BeanDefinition
BeanDefinitionReader
BeanDefinitionRegistry
ApplicationContext
Aware
```
**生命周期-后置处理器**
```java
BeanFactoryPostProcessor
InitializingBean
BeanPostProcessor
```
### Resource资源
#### 方法
快捷键:ctrl+F12 看类的方法
#### 实现类
快捷键:ctrl+h 查看接口实现类
1. ContextResource:表示可以拿Web环境的资源
2. HttpResource:可以从网络中拿到资源
3. WritableResource:
1. FileSystemResource:可以从文件系统拿到资源
2. FileUrlResource:URL就是统一资源定位符的意思;URL可以定位到网络,磁盘,等任何你想定位到的位置;表示Spring几乎可以从任何地方拿到资源。
4. AbstractResource
1. ByteArrayResource:从byte数组拿到资源
2. InputStreamResource:从Input流中拿到资源
5. 综合来说Spring几乎可以从任何地方拿到资源。
### ResourceLoader资源加载器
此类的源码开头有这样一句话,Strategy interface(策略接口),显然用到了策略模式。策略体现在哪个地方,我们下面再说。
> Strategy interface for loading resources (e.g., class path or file systemresources)
#### 方法
```java
/**
* Strategy interface(策略接口) for loading resources (e.g., class path or file system
* resources). An {@link org.springframework.context.ApplicationContext}
* is required to provide this functionality plus extended
* {@link org.springframework.core.io.support.ResourcePatternResolver} support.
*
*
{@link DefaultResourceLoader} is a standalone implementation that is * usable outside an ApplicationContext and is also used by {@link ResourceEditor}. * *
Bean properties of type {@code Resource} and {@code Resource[]} can be populated * from Strings when running in an ApplicationContext, using the particular * context's resource loading strategy. * * @author Juergen Hoeller * @since 10.03.2004 * @see Resource * @see org.springframework.core.io.support.ResourcePatternResolver * @see org.springframework.context.ApplicationContext * @see org.springframework.context.ResourceLoaderAware */ public interface ResourceLoader { /** Pseudo URL prefix for loading from the class path: "classpath:". */ String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX; /** * Return a {@code Resource} handle for the specified resource location. *
The handle should always be a reusable resource descriptor, * allowing for multiple {@link Resource#getInputStream()} calls. *
Note that a {@code Resource} handle does not imply an existing resource; * you need to invoke {@link Resource#exists} to check for existence. * @param location the resource location * @return a corresponding {@code Resource} handle (never {@code null}) * @see #CLASSPATH_URL_PREFIX * @see Resource#exists() * @see Resource#getInputStream() */ Resource getResource(String location); //这个是最关键的 /** * Expose the {@link ClassLoader} used by this {@code ResourceLoader}. *
Clients which need to access the {@code ClassLoader} directly can do so
* in a uniform manner with the {@code ResourceLoader}, rather than relying
* on the thread context {@code ClassLoader}.
* @return the {@code ClassLoader}
* (only {@code null} if even the system {@code ClassLoader} isn't accessible)
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
* @see org.springframework.util.ClassUtils#forName(String, ClassLoader)
*/
@Nullable
ClassLoader getClassLoader();
}
```
#### 实现类
1. DefaultResourceLoader:默认资源加载器
1. ClassRelativeResourceLoader:能读取类路径相对路径
2. FileSystemResourceLoader:能读取文件系统的
3. ServletContextResourceLoader:能读取web环境的
### BeanFactory-Bean工厂
```java
/**
* The root interface for accessing a Spring bean container.
* 根接口,整个访问容器的入口
*
This is the basic client view of a bean container; * further interfaces such as {@link ListableBeanFactory} and * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} * are available for specific purposes. * *
This interface is implemented by objects that hold a number of bean definitions,
* 保存很多的BeanDefinition信息,都有一个唯一的名字
* each uniquely identified by a String name. Depending on the bean definition,
* the factory will return either an independent instance of a contained object
* (the Prototype design pattern【原型模式】), or a single shared instance (a superior
* alternative to the Singleton design pattern【单例设计模式】, in which the instance is a
* singleton in the scope of the factory). Which type of instance will be returned
* depends on the bean factory configuration: the API is the same. Since Spring
* 2.0, further scopes are available depending on the concrete application
* context (e.g. "request" and "session" scopes in a web environment).
*
*/
public interface BeanFactory {
//省略...
}
```
> 源码分析小技巧:看源码时,我们可以先看一个类的接口继承关系,因为接口就是规范,大部分开源框架源码都是遵守这一规范的。
1. BeanFactory
1. HierarchicalBeanFactory:定义父子工厂(父子容器)
2. ListableBeanFacotory:实现是DefaultListableBeanFactory,保存了ioc容器中的核心信息。
3. AutowireCapableBeanFactory:提供自动装配能力
4. AnnotationApplicationContext:组合了**一个总的注册中心**(DefaultListableBeanFactory),它有自动装配能力。
#### AbstractApplicationContext
环境类的意思就是谁持有这个策略;这里就解释了上文说ResourceLoader是环境类接口
```java
// 策略模式的环境类
private ResourcePatternResolver resourcePatternResolver;
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
```
#### GenericApplicationContext
这里组合了DefaultListableBeanFactory
```java
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
}
```
#### DefaultListableBeanFactory
```java
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Map from serialized id to factory instance. */
//组合模式,Spring里面可以有很多工厂,每一个工厂有自己的ID,好处就是工厂之间的bean可以隔离起来,但是用的很少
private static final Map
1. BeanDefinitionRegistry:Bean定义信息注册中心
2. SimpleAliasRegistry:别名注册中心
3. SingletonBeanRegistry:单实例注册中心
4. BeanFactory:Bean工厂
5. AutowireCapableBeanFactory:有自动装配能力的Bean工厂
6. DefaultListableBeanFactory:可以理解为拥有上面所有注册中心功能的一个总的注册中心
7. GenericApplicationContext有一个我们常用的实现类AnnotationConfigApplicationContext,就是注解版的IOC容器
8. 虽然我们的IOC容器和DefaultListableBeanFactory没有继承的父子关系,但是却组合了DefaultListableBeanFactory,拥有了它的全部功能。
9. DefaultListableBeanFactory在Spring中扮演着至关重要的角色。
> 1. DefaultListableBeanFactory保存了所有对象(bean)的图纸(也就是类模板),并没有真正存对象。
> 2. 我们这里猜想一下,Spring底层真正存Bean的地方用的是哪个数据结构呢?是List,还是Set,还是Map。咱们稍微想一下就知道肯定是Map,并且Key是beanName,value是真正的Bean。如果不是Map的话,如何通过BeanName拿到对应的Bean呢?
> 3. 其实就是上面的那个beanDefinitionMap
### 注册BeanDefinition-1
#### 流程图-BeanDefinition注册流程
- 我们要看BeanDefinition是何时被放入到beanDefinitionMap,只需要在DefaultListableBeanFactory用到`beanDefinitionMap.put()`的地方打个断点。
- 我们在DefaultListableBeanFactory里搜索,发现了registerBeanDefinition(注册Bean定义信息)这个方法名很像我们要找的东西,再看里面的代码,果然有`beanDefinitionMap.put()`这串代码,我们试着在这里打个断点
- 然后启动下面的测试类
- 上面就是我们看一个框架源码,可以往哪些方向去猜测。
#### MainTest测试类
```java
public class MainTest {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person bean = context.getBean(Person.class);
System.out.println(bean);
}
}
```
#### Debug调用栈
> 调用栈的调用顺序已经非常清楚了,可以把图放大一点看,下面只说一些必要的信息。
1. `new ClassPathXmlApplicationContext("beans.xml")`这一步开始就要刷新容器了
2. 调用`AbstractApplicationContext#refresh()`这个方法,`refresh()`方法是容器刷新的几大步所在地
#### AbstractApplicationContext#refresh()容器刷新
```java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// BeanFactory第一次开始创建的时候,有xml解析逻辑。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// ......
// Instantiate all remaining (non-lazy-init) singletons.
//完成 BeanFactory 初始化
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
// ......
}
}
```
#### AbstractApplicationContext#obtainFreshBeanFactory()第一次开始创建BeanFactory
```java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); //刷新整个BeanFactory
return getBeanFactory();
}
```
#### AbstractRefreshableApplicationContext#refreshBeanFactory()刷新整个BeanFactory
```java
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory(); //创建保存所有Bean定义信息的档案馆
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); //开始加载Bean定义信息
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
```
#### AbstractXmlApplicationContext#loadBeanDefinitions()加载Bean定义信息
下面就是一堆的loadBeanDefinitions调用,调用顺序就是我下面写的代码顺序。
```java
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory. 准备读取xml内容的读取器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this); //持有ioc容器的环境类
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations(); //可以一次传入很多配置文件
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations); //读取文件
}
}
```
#### AbstractBeanDefinitionReader#loadBeanDefinitions()
下面也是一堆的loadBeanDefinitions调用,调用顺序就是我下面写的代码顺序。
```java
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) { //加载每一个配置文件里面的内容
count += loadBeanDefinitions(location);
}
return count;
}
@Override //加载指定配置文件的所有内容
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set
> 前面的调用栈都是一样的,从下面开始不一样
#### DefaultBeanDefinitionDocumentReader#processBeanDefinition()
```java
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //把当前标签解析完了,BeanDefinition和beanName都封装在了Holder中
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event. //发送一个通知事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
```
#### BeanDefinitionParserDelegate#parseBeanDefinitionElement()
```java
public static final String ID_ATTRIBUTE = "id";
public static final String NAME_ATTRIBUTE = "name";
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List
1. ioc事件派发器
2. 国际化解析
3. bean工厂功能---自动装配被组合进来的
4. 资源解析功能
5. 等等
> 这个就是我们常说的IOC容器
### Aware接口功能分析
1. aware中文翻译是**意识到的,察觉到的,发现**这么个意思。从翻译来看,aware做的事情应该是发现某一个东西。
```java
/**
* Marker superinterface indicating that a bean is eligible to be
* notified by the Spring container of a particular framework object
* through a callback-style method. Actual method signature is
* determined by individual subinterfaces, but should typically
* consist of just one void-returning method that accepts a single
* argument.
*/
public interface Aware {
}
```
2. 注释的大致意思是:Aware是一个标记性的超接口(顶级接口),指示了一个Bean有资格通过回调方法的形式获取Spring容器底层组件。实际回调方法被定义在每一个子接口中,而且通常一个子接口只包含一个接口一个参数并且返回值为void的方法。
3. 说白了:只要实现了Aware子接口的Bean都能获取到一个Spring底层组件。
比如实现了ApplicationContextAware接口,实现它的方法,就能通过回调机制拿到ApplicationContext
#### 创建Person对象
##### 流程图-Bean对象创建流程
##### Debug调用栈
为了知道Aware的原理,我们给上面的pos_1和pos_2位置打上断点,看下是怎么进来的
**Person**
```java
@Component
public class Person implements ApplicationContextAware, MessageSourceAware {
ApplicationContext context; //我们不用@Autowired也可以要到ioc容器
MessageSource messageSource;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Person(){
System.out.println("person创建...."); //pos_1
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//利用回调机制,把ioc容器传入
this.context = applicationContext; //pos_2
}
@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
}
```
**AnnotationMainTest**
```java
/**
* 注解版Spring的用法
*/
public class AnnotationMainTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person bean = applicationContext.getBean(Person.class);
ApplicationContext context = bean.getContext();
System.out.println(context == applicationContext);
}
```
**MainConfig**
```java
@ComponentScan("cn.imlql.spring")
@Configuration
public class MainConfig {
public Person person(){
Person person = new Person();
person.setName("李四");
return person;
}
}
```
1. 有一些一样的东西不再赘述
2. 在`AbstractApplicationContext#refresh()`里会调用
##### AbstractApplicationContext#finishBeanFactoryInitialization()完成 BeanFactory 初始化
```java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// BeanFactory第一次开始创建的时候,有xml解析逻辑。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// ...
try {
// Instantiate all remaining (non-lazy-init) singletons.
//完成 BeanFactory 初始化
finishBeanFactoryInitialization(beanFactory);
}
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有的单实例Bean
beanFactory.preInstantiateSingletons();
}
```
##### DefaultListableBeanFactory#preInstantiateSingletons()循环遍历beanDefinitionName
```java
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
List
前面有很多一样的调用链,不再赘述。从doCreateBean:602调用栈开始不一样
##### AbstractAutowireCapableBeanFactory#doCreateBean()
```java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
```
##### ApplicationContextAwareProcessor
```java
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
//...
else {
invokeAwareInterfaces(bean); //执行aware接口规定的方法
}
return bean;
}
//就是在这里执行Aware回调
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
```
## 属性赋值的时机(XML版)
### Debug调用栈
**Person**
```java
public class Person implements ApplicationContextAware, MessageSourceAware {
ApplicationContext context; //我们不用@Autowired也可以要到ioc容器
MessageSource messageSource;
public void setName(String name) {
this.name = name; // pos_2
}
public String getName() {
return name;
}
public Person(){
System.out.println("person创建...."); //pos_1
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//利用回调机制,把ioc容器传入
this.context = applicationContext;
}
@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
}
```
**MainTest**
```java
public class MainTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person bean = context.getBean(Person.class);
System.out.println(bean);
}
}
```
**beans.xml**
```xml
还是老规矩,一样的就不说了,从调用栈不一样的地方开始说起。多看几遍,看到后面就会发现思路越来越清晰了。
### AbstractAutowireCapableBeanFactory#doCreateBean()
```java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean. 这里面封装好了真正的Person对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//创建Bean的实例,默认使用无参构造器创建的对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//......
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper); //给创建好的对象每个属性进行赋值
exposedObject = initializeBean(beanName, exposedObject, mbd);//初始化bean
}
return exposedObject;
}
```
我们看到此时,Person的name属性还是null
### AbstractAutowireCapableBeanFactory#populateBean()属性赋值
```java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 这一步就是拿到属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// ......
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs); //xml版的所有配置会来到这里给属性赋值
}
}
```
这里拿到属性值
```java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// ......
// Set our (possibly massaged) deep copy.
try { //深拷贝所有PropertyValue应该对应的属性
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
}
```
bw就是上面说的 => 里面封装好了真正的Person对象
这里就是一层一层调,不重要跳过。
### AbstractNestablePropertyAccessor#processLocalProperty
```java
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
// ...
try {
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
ph.setValue(valueToApply);
}
//...
}
```
### BeanWrapperImpl内部类BeanPropertyHandler#setValue()
```java
private class BeanPropertyHandler extends PropertyHandler {
@Override
public void setValue(@Nullable Object value) throws Exception {
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction