GetBean源码全面解读

作者: Java大宝宝 | 来源:发表于2018-12-21 14:59 被阅读0次

    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性能优化、分布式架构等这些成为架构师必备

    相关文章

      网友评论

        本文标题:GetBean源码全面解读

        本文链接:https://www.haomeiwen.com/subject/ecgmkqtx.html