Java 杂谈Java进阶学习

GetBean源码全面解读

2018-12-21  本文已影响0人  Java大宝宝

GetBean源码部分

protected  T doGetBean(finalStringname,@NullablefinalClass requiredType,

@NullablefinalObject[] args, boolean typeCheckOnly) throws BeansException {

//会包括解析别名等操作

finalStringbeanName = transformedBeanName(name);

Objectbean;

// 先检查单例列表中是否已经注册了这个bean

ObjectsharedInstance = getSingleton(beanName);

if(sharedInstance !=null&& args ==null) {

bean = getObjectForBeanInstance(sharedInstance, name, beanName,null);

}

else{

// 检查bean是否并发被创建

if(isPrototypeCurrentlyInCreation(beanName)) {

thrownewBeanCurrentlyInCreationException(beanName);

}

// 检查是否在父类工厂中,逻辑和这个差不多,这里省略....

//标记bean正在被创建

if(!typeCheckOnly) {

markBeanAsCreated(beanName);

}

try{

//合并父类中的方法及属性,下面会细讲                      

finalRootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

//检查这个bean是否为抽象类

checkMergedBeanDefinition(mbd, beanName, args);

// 这里是为了保证获取的bean的依赖都需要先生成

String[] dependsOn = mbd.getDependsOn();

if(dependsOn !=null) {

for(Stringdep : dependsOn) {

if(isDependent(beanName, dep)) {

thrownewBeanCreationException(mbd.getResourceDescription(), beanName,

"Circular depends-on relationship between '"+ beanName +"' and '"+ dep +"'");

}

registerDependentBean(dep, beanName);

try{

getBean(dep);

}

catch(NoSuchBeanDefinitionException ex){

throwex;

}

}

}

// 创建单例的bean,看下方的createBean方法

if(mbd.isSingleton()) {

sharedInstance = getSingleton(beanName, () -> {

try{

returncreateBean(beanName, mbd, args);

}

catch(BeansException ex) {

destroySingleton(beanName);

throwex;

}

});

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

}

elseif(mbd.isPrototype()) {

// It's a prototype -> create a new instance.

ObjectprototypeInstance =null;

try{

beforePrototypeCreation(beanName);

prototypeInstance = createBean(beanName, mbd, args);

}

finally{

afterPrototypeCreation(beanName);

}

bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

}

else{

StringscopeName = mbd.getScope();

finalScope scope =this.scopes.get(scopeName);

if(scope ==null) {

thrownewIllegalStateException("No Scope registered for scope name '"+ scopeName +"'");

}

try{

ObjectscopedInstance = scope.get(beanName, () -> {

beforePrototypeCreation(beanName);

try{

returncreateBean(beanName, mbd, args);

}

finally{

afterPrototypeCreation(beanName);

}

});

bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

}

catch(IllegalStateException ex) {

thrownewBeanCreationException(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);

throwex;

}

}

// 检查需要的类型和实际传参类型是否一致. 这里省略....

return(T) bean;

}

整个操作大概是以下几步:

获取实际的beanName,其中会处理带&号前缀的beanName,并解析别名。

检查单例列表中是否存在该beanName的bean,若存在则无需走下面的创建bean的流程。

若单例列表中并不存在此bean,则检查是否有并发创建。这里的判断只针对scope为prototype类型的bean。

检查bean是否存在于父类工厂中,若存在,则走父类工厂的getBean流程。向上委托,保证容器中只会存在一个同名的bean。

标记bean正在被创建。

如果有父类,这里会递归合并父类的方法以及属性。并会用自己重写的方法覆盖其父类的方法。合并完成并检查这个bean的是否是抽象类。

如果该bean上有注解@DependsOn,或者配置文件上配置有该属性,则需保证该bean的所有依赖需要先在容器内注册。

分单例和原型以及其他scope类型来创建bean。

检查需要的类型和生成的bean类型是否一致。

返回创建好的bean。

getSingleton源码部分(beanName,allowEarlyReference)

这里的singletonObjects是一个缓存了beanName和bean的Map,若存在,直接返回。

不存在,则检查是否这个bean是否正在创建的过程中,先检查earlySingletonObjects这个容器,这个容器里面放着的是已经构造完成但是没有注入属性的对象,若存在,也会直接返回。

尝试着从singletonFactories中获取,然后调用getObject方法去获取对象。并将获取到的对象放到earlySingletonObjects容器中,然后从singletonFactories容器中移除。

这里这么设计是为了解决循环依赖的问题。若A依赖B,B依赖C,C又依赖A,这样三个bean就形成了一个环(这里只是针对set方法注入的bean,构造器注入还是会有循环依赖的问题而抛出异常的),spring会将创建的bean实例提前暴露在缓存中,一旦下一个bean创建的时候需要依赖上个bean,则直接使用ObjectFactory来获取bean。

这里举个生活中的例子阐述下:就拿建一个小区房来说,建房子是一个很复杂的工序,但是咱们只要把架子搭好,告诉大家这块地是用来建这个房子的就行。至于其他装修,家私等等东西都可以后面再进行补充。咱们不能搭架子的时候去放家具吧,这样整个都会乱套,也不符合常理。(这里房子的框架是咱们程序中的一个对象A,家具是另一个对象B,A依赖B,B依赖A)

循环依赖

相关的逻辑有用到以下代码段:

每次singleton bean创造之前都会调用的方法,在singletonsCurrentlyInCreation容器中加入这个bean的beanName,标记这个bean正在创建中,供后期生成ObjectFactory。这里有个inCreationCheckExclusions容器,在这里我理解为属于该容器的bean必须要初始化完成才允许被获取。也就是说,添加进该容器后bean便不会允许早期的循环依赖了。

上面的代码片段的调用在doCreateBean源码中(排在bean对象创建之后和属性注入之前),可以观察到要执行addSingletonFactory方法需要满足三个条件:

这个bean是单例的,

允许循环依赖,

这个bean正在被创建的过程中。

在满足这三个条件的情况下,会在singletonFactories容器中缓存一个生成该bean的工厂,将其提前暴露出去。这里关注下getEarlyBeanReference(beanName, mbd, bean)这个方法,实际上ObjectFactory中getObject方法调用的也是这个方法。

getMergedBeanDefinition源码部分

看这部分之前,首先得明白BeanDefinition是用来干什么的,这个类会在整个源码解析过程中出现无数次。Spring把BeanDefinition定义成IOC容器的内部数据结构,实际上它也就是POJO对象在IOC容器中的抽象,通过这个对象,IOC容器能很方便的对Bean进行管理,包括利用它进行属性的注入等等…

protectedRootBeanDefinitiongetMergedBeanDefinition(

String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)

throwsBeanDefinitionStoreException

{

synchronized(this.mergedBeanDefinitions) {

RootBeanDefinition mbd =null;

// 重新去获取一次,有可能该BeanDefinition已经生成

if(containingBd ==null) {

mbd =this.mergedBeanDefinitions.get(beanName);

}

if(mbd ==null) {

if(bd.getParentName() ==null) {

// 没有父类则深拷贝一个RootBeanDefinition

if(bdinstanceofRootBeanDefinition) {

mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();

}

else{

mbd =newRootBeanDefinition(bd);

}

}

else{

// 有父类则需要先获取父类的BeanDefinition,流程和获取子类的BeanDefinition一致

BeanDefinition pbd;

try{

String parentBeanName = transformedBeanName(bd.getParentName());

if(!beanName.equals(parentBeanName)) {

pbd = getMergedBeanDefinition(parentBeanName);

}

else{

BeanFactory parent = getParentBeanFactory();

if(parentinstanceofConfigurableBeanFactory) {

pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);

}

else{

thrownewNoSuchBeanDefinitionException(parentBeanName,

"Parent name '"+ parentBeanName +"' is equal to bean name '"+ beanName +

"': cannot be resolved without an AbstractBeanFactory parent");

}

}

}

catch(NoSuchBeanDefinitionException ex) {

thrownewBeanDefinitionStoreException(bd.getResourceDescription(), beanName,

"Could not resolve parent bean definition '"+ bd.getParentName() +"'", ex);

}

//这里进行深拷贝,并将子类重写的方法和属性进行覆盖

mbd =newRootBeanDefinition(pbd);

mbd.overrideFrom(bd);

}

// 若前面没配置scope类型,这里设置为单例范围

if(!StringUtils.hasLength(mbd.getScope())) {

mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);

}

// 这里对内部类做了一些处理,若包含它的bean不是单例的,则该bean也将不会是单例的

if(containingBd !=null&& !containingBd.isSingleton() && mbd.isSingleton()) {

mbd.setScope(containingBd.getScope());

}

// 将生产的BeanDefinition 缓存起来

if(containingBd ==null&& isCacheBeanMetadata()) {

this.mergedBeanDefinitions.put(beanName, mbd);

}

}

returnmbd;

}

}

在mergedBeanDefinitions同步的情况下再次读取缓存,防止该BeanDefinition已经被合并过了。

检查是否有父类,若有父类,则必须递归去合并BeanDefinition。

将子类重写后的方法覆盖到定义的BeanDefinition中。

设置scope类型。

将生成的BeanDefinition缓存起来。

registerDependentBean源码部分

这一部分应该还是很容易理解的,这里面出现了两个Map,一个是dependentBeanMap,它主要用来装载键为beanName值为dependentBeanName的容器,另一个dependenciesForBeanMap是用来装载键为dependentBeanName值为beanName的容器,这样可以方便我们观察一个类需要组装哪些依赖,然后这个类同时是哪些类的依赖。

getSingleton源码部分(beanName,singletonFactory)

publicObject getSingleton(String beanName, ObjectFactory singletonFactory) {

Assert.notNull(beanName,"Bean name must not be null");

synchronized (this.singletonObjects) {

//先去singletonObjects容器中去获取,能获取到就直接返回了

Object singletonObject =this.singletonObjects.get(beanName);

if(singletonObject ==null) {

//调用destroySingletons方法singletonsCurrentlyInDestruction属性才会变成true

if(this.singletonsCurrentlyInDestruction) {

thrownew Exception("xx"));

}

//这里会将beanName缓存到singletonsCurrentlyInCreation集合中

beforeSingletonCreation(beanName);

boolean newSingleton =false;

boolean recordSuppressedExceptions = (this.suppressedExceptions ==null);

if(recordSuppressedExceptions) {

this.suppressedExceptions = new LinkedHashSet<>();

}

try{

//这里会触发下面的createBean方法

singletonObject = singletonFactory.getObject();

newSingleton =true;

}

catch(IllegalStateException ex) {

// 如果是与此同时被创建了,则直接获取,如果能获取到值不为null,则正常返回。

//(注意这里捕获异常正常返回的话就不会走下面的addSingleton方法了。)

singletonObject =this.singletonObjects.get(beanName);

if(singletonObject ==null) {

throwex;

}

}

catch(BeanCreationException ex) {

if(recordSuppressedExceptions) {

for(Exception suppressedException :this.suppressedExceptions) {

ex.addRelatedCause(suppressedException);

}

}

throwex;

}

finally{

if(recordSuppressedExceptions) {

this.suppressedExceptions =null;

}

//这里会将beanName从singletonsCurrentlyInCreation集合中移除

afterSingletonCreation(beanName);

}

if(newSingleton) {

//添加到singletonObjects和registeredSingletons缓存中,并从singletonFactories和earlySingletonObjects中移除

addSingleton(beanName, singletonObject);

}

}

returnsingletonObject;

}

}

直接去singletonObjects中获取,获取到了便直接返回。

获取不到,先将beanName缓存到singletonsCurrentlyInCreation集合中,作为标记表示该bean正在被创建的过程中。

触发createBean方法去创建bean,这里可以去看一下ObjectFactory这个接口工厂,这里是对getObject方法的一个回调(AbstractAutowireCapableBeanFactory中的createBean方法)。

创建bean的过程中在不出异常的情况下便会进行下图的操作后并返回,也就操作了几个容器的缓存而已。

createBean源码部分

这一块不是很复杂,复杂的地方在doCreateBean这个方法中。

protectedObjectcreateBean(StringbeanName, RootBeanDefinition mbd,@NullableObject[] args)

throws BeanCreationException {

RootBeanDefinition mbdToUse = mbd;

// 要保证RootBeanDefinition的beanClass是存在的

Class resolvedClass = resolveBeanClass(mbd, beanName);

if(resolvedClass !=null&& !mbd.hasBeanClass() && mbd.getBeanClassName() !=null) {

mbdToUse =newRootBeanDefinition(mbd);

mbdToUse.setBeanClass(resolvedClass);

}

// 这一块没什么研究,注解意思是(检查所有带有override的方法是否都是存在的)

try{

mbdToUse.prepareMethodOverrides();

}

catch(BeanDefinitionValidationException ex) {

}

try{

//这一块我猜测大概是看咱们自己有提供实例化的方法不,若有,则不会走下面的doCreateBean方法。

Objectbean = resolveBeforeInstantiation(beanName, mbdToUse);

if(bean !=null) {

returnbean;

}

}

catch(Throwable ex) {

}

try{

//创建bean的真正方法

ObjectbeanInstance = doCreateBean(beanName, mbdToUse, args);

}

returnbeanInstance;

}

catch(Exception e){

throwe;

}

}

doCreateBean源码部分

protectedObjectdoCreateBean(finalStringbeanName,finalRootBeanDefinition mbd,final@NullableObject[] args)

throws BeanCreationException {

// Instantiate the bean.

BeanWrapper instanceWrapper =null;

if(mbd.isSingleton()) {

instanceWrapper =this.factoryBeanInstanceCache.remove(beanName);

}

if(instanceWrapper ==null) {

// 创建这个bean,真正构建时有分两种情况,jdk反射和cglib动态代理

instanceWrapper = createBeanInstance(beanName, mbd, args);

}

finalObjectbean = instanceWrapper.getWrappedInstance();

Class beanType = instanceWrapper.getWrappedClass();

if(beanType != NullBean.class) {

mbd.resolvedTargetType = beanType;

}

// 允许后置处理器来修改这个BeanDefinition

synchronized (mbd.postProcessingLock) {

if(!mbd.postProcessed) {

try{

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

}

catch(Throwable ex) {

thrownewBeanCreationException(mbd.getResourceDescription(), beanName,

"Post-processing of merged bean definition failed", ex);

}

mbd.postProcessed =true;

}

}

// 用来解决循环依赖问题的,上面已经有过详细解释了。看上面循环依赖模块

boolean earlySingletonExposure = (mbd.isSingleton() &&this.allowCircularReferences &&

isSingletonCurrentlyInCreation(beanName));

if(earlySingletonExposure) {

if(logger.isTraceEnabled()) {

logger.trace("Eagerly caching bean '"+ beanName +

"' to allow for resolving potential circular references");

}

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

}

// Initialize the bean instance.

ObjectexposedObject = bean;

try{

//进行属性的注入,调用bean的set方法进行字段的初始化

populateBean(beanName, mbd, instanceWrapper);

//进行一些初始化方法的调用,比如afterPropertiesSet等等。

exposedObject = initializeBean(beanName, exposedObject, mbd);

}

catch(Throwable ex) {

if(ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {

throw(BeanCreationException) ex;

}

}

if(earlySingletonExposure) {

ObjectearlySingletonReference = getSingleton(beanName,false);

if(earlySingletonReference !=null) {

if(exposedObject == bean) {

exposedObject = earlySingletonReference;

}

//在出现循环依赖后,从earlySingletonObjects中获取的bean对象和initializeBean后

//的不一致,证明被后置处理器处理过了,前后bean不一致,需要抛出异常

elseif(!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {

String[] dependentBeans = getDependentBeans(beanName);

Set actualDependentBeans =newLinkedHashSet<>(dependentBeans.length);

for(StringdependentBean : dependentBeans) {

if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {

actualDependentBeans.add(dependentBean);

}

}

if(!actualDependentBeans.isEmpty()) {

thrownewBeanCurrentlyInCreationException(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.");

}

}

}

}

// 注册bean的销毁方法

try{

registerDisposableBeanIfNecessary(beanName, bean, mbd);

}

catch(BeanDefinitionValidationException ex) {

thrownewBeanCreationException(

mbd.getResourceDescription(), beanName,"Invalid destruction signature", ex);

}

returnexposedObject;

}

doCreateBean大概有以下步骤:

调用createBeanInstance方法初始化bean实例,这里不包括属性的注入。

调用合并bean的后置处理器修改这个bean的BeanDefinition的一些定义。即调用MergedBeanDefinitionPostProcessor的实现类的postProcessMergedBeanDefinition方法对BeanDefinition进行一些额外的处理。

为早期的循环依赖做准备,将包装了bean的工厂方法塞到singletonFactories中。

调用populateBean方法进行一些属性的注入。

执行initializeBean方法进行一些初始化方法的调用,例如:afterPropertiesSet方法的调用。与此同时,其后置处理器有可能对指定的bean进行增强。

如果出现了bean的增强,然后又有依赖它的类先生成,则需抛出异常。例如:对象A被增强了,得到A+对象,而此时对象B有依赖对象A,循环依赖时通过singletonFactories获取到的对象却是增强前的A对象,这时就会出现问题。如果不抛出异常,spring容器缓存的是A+对象,但是B引用的却是A,这样就会出现不可预测的问题。

instantiateBean源码

这里是createBeanInstance方法中最终调用的方法,这里有三个流程:

进行对象的构造,这里关注下CglibSubclassingInstantiationStrategy这个策略类,有继承SimpleInstantiationStrategy类,调用其instantiate可以调用对象的构造器进行对象的初始化,在BeanDefinition属性MethodOverrides不存在时,可以用jdk的反射进行获取对象,否则则必须使用cglib动态代理。(这里的MethodOverrides的存在需要对象中某个方法用@Lookup注解修饰,或者XML定义中有 lookup-method属性

用BeanWrapperImpl对生成的对象进行包装,并激活注册默认编辑器的属性。

注册默认的编辑器,然后将ConversionService这个类的引用设置到BeanWrapper对象上。ConversionService是用来进行类型转换的,里面的属性converters用一个map维护着各种类型的转换器。

populateBean源码部分

下面关注几个重点代码,省略了一些代码,可以自己去翻阅下:

protectedvoidpopulateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw){

......

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() :null);

if(mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {

MutablePropertyValues newPvs =newMutablePropertyValues(pvs);

// 这里是根据bean名称进行依赖注入的

if(mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {

autowireByName(beanName, mbd, bw, newPvs);

}

// 这里是根据bean的类型进行依赖注入的

if(mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {

autowireByType(beanName, mbd, bw, newPvs);

}

pvs = newPvs;

}

......

if(pvs !=null) {

//实际上注入属性值的方法,这里是populateBean方法的重点

applyPropertyValues(beanName, mbd, bw, pvs);

}

}

这里注释下applyPropertyValues的部分源码:

protectedvoidapplyPropertyValues(StringbeanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {

MutablePropertyValues mpvs =null;

List original;

if(pvsinstanceofMutablePropertyValues) {

mpvs = (MutablePropertyValues) pvs;

if(mpvs.isConverted()) {

// 这里可以迅速返回。当这个PropertyValues对象中的值都是处理过后便可以触发。状态值会在下面几行代码设置。

try{

bw.setPropertyValues(mpvs);

return;

}

catch(BeansException ex) {

thrownewBeanCreationException(

mbd.getResourceDescription(), beanName,"Error setting property values", ex);

}

}

original = mpvs.getPropertyValueList();

}

else{

original = Arrays.asList(pvs.getPropertyValues());

}

TypeConverter converter = getCustomTypeConverter();

if(converter ==null) {

converter = bw;

}

BeanDefinitionValueResolver valueResolver =newBeanDefinitionValueResolver(this, beanName, mbd, converter);

// 这里是个深拷贝,解析所有引用的值。

List deepCopy =newArrayList<>(original.size());

boolean resolveNecessary =false;

for(PropertyValue pv : original) {

if(pv.isConverted()) {

deepCopy.add(pv);

}

else{

StringpropertyName = pv.getName();

ObjectoriginalValue = pv.getValue();

//这里的resolveValueIfNecessary是一个需要关注的方法,有兴趣的小伙伴可以点进去看看,

//里面封装了针对各种类型的属性的解析,例如List,Map,Set等等类型。

ObjectresolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

ObjectconvertedValue = resolvedValue;

boolean convertible = bw.isWritableProperty(propertyName) &&

!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);

if(convertible) {

convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);

}

//为了避免每次创建都去转换属性

if(resolvedValue == originalValue) {

//这里的触发条件必须为该属性得是有写权限的,并且里面不能带有“.”和“[”这个符号,这里我的理解是

//teacher.name以及student[1].name这样的propertyName便不能触发这个条件

if(convertible) {

pv.setConvertedValue(convertedValue);

}

deepCopy.add(pv);

}

elseif(convertible && originalValueinstanceofTypedStringValue &&

!((TypedStringValue) originalValue).isDynamic() &&

!(convertedValueinstanceofCollection || ObjectUtils.isArray(convertedValue))) {

//这一块的条件比上一个多了几个,源值必须是string类型,且不能是动态的,并且不能是集合和数组中的任意一个。

pv.setConvertedValue(convertedValue);

deepCopy.add(pv);

}

else{

//条件在这里触发后就不会打开快捷返回的开关了

resolveNecessary =true;

deepCopy.add(newPropertyValue(pv, convertedValue));

}

}

}

//设置converted状态值,供其组装属性时快捷返回。

if(mpvs !=null&& !resolveNecessary) {

mpvs.setConverted();

}

// 将我们深拷贝出来的值设置到包装类BeanWrapperImpl包装的对象上

try{

bw.setPropertyValues(newMutablePropertyValues(deepCopy));

}

catch(BeansException ex) {

thrownewBeanCreationException(

mbd.getResourceDescription(), beanName,"Error setting property values", ex);

}

}

setPropertyValues方法的源码最终调用的是AbstractNestablePropertyAccessor类的setPropertyValue方法,在这里BeanWrapperImpl是它的实现类,从名字上看也能猜出来这个类是个处理嵌套属性的访问器。

publicvoidsetPropertyValue(String propertyName, @Nullable Objectvalue) throws BeansException{

AbstractNestablePropertyAccessor nestedPa;

try{

//这里可以解析嵌套的属性

nestedPa = getPropertyAccessorForPropertyPath(propertyName);

}

catch(NotReadablePropertyException ex) {

thrownewNotWritablePropertyException(getRootClass(),this.nestedPath + propertyName,

"Nested property in path '"+ propertyName +"' does not exist", ex);

}

//这里获取到了最终解析到的属性名

PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));

//给最终解析到的属性名赋值操作

nestedPa.setPropertyValue(tokens,newPropertyValue(propertyName,value));

}

上面有个getPropertyAccessorForPropertyPath方法,点进去会发现他会有个解析“.”和“[]”的方法getNestedPropertySeparatorIndex,它的作用我举个例子来说明一下:一个班级有多个学生,我想设置某个学生的名字,班级是个Class对象,里面有属性:private Student[] students这里我想修改下student[2]的name属性,我就必须先用getStudent方法取出 Student[] 数组,然后再在 Student[] 数组中找到索引为2的Student,最后修改Student身上的name属性。

GetBean流程图

在此我向大家推荐一个架构学习交流群。交流学习群号:938837867 暗号:555 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备

上一篇下一篇

猜你喜欢

热点阅读