ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

spring 5.0.21.BUILD-SNAPSHOT源码解读,第二集(Spring循环依赖解决方案)

2020-12-29 20:02:26  阅读:227  来源: 互联网

标签:5.0 String mbd beanName descriptor bean 源码 null 第二集


1.老办法,代码放在码云:

 https://gitee.com/rich_lz/spring_kz 所属分支:springReferDepends;

2.循环依赖代码演示:

@Repository
public class TestDao {
  /**
   *
   *dao层依赖TestService
*/
@Autowired private TestService testservice; public String sayHello(String name){ System.out.println("接口调用==>"+name); return name; } }
@Service(value = "TestService")
public class TestService  {
  
  
  /**
  *TestService 又依赖TestDao
  *
  **/
@Autowired private TestDao testDao; @Autowired TestService(TestDao testDao){ this.testDao = testDao; } public String test(String name){ return testDao.sayHello(name); } }

 3.代码调试:

  通过第一集的内容,我们大概了解到spring先要加载bean,然后再实例化,那么我们很容易就想到发生循环依赖肯定是在实例化的过程中,那么我们就很容易的找到我们需要调试的地方了,AbstractApplicationContext.refresh()

     这个方法中一共有11个方法,真正实例化bean的地方是在 finishBeanFactoryInitialization(beanFactory); 内,通过源码跟踪定位到DefaultListableBeanFactory.preInstantiateSingletons()。

@Override
    public void preInstantiateSingletons() throws BeansException {
        if (logger.isDebugEnabled()) {
            logger.debug("Pre-instantiating singletons in " + this);
        }

        // 获取到所有已经定义好,并且放到list集合中的bean.
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // 这个bean不是抽象的,是单例,不是懒加载。 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);

            //实现FactoryBean接口的bean. if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else {
            //核心方法,普通定义的bean。 getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }

 

   4.再打开getBean方法再往下跟会发现调用的事AbstractBeanFactory.doGetBean()方法:

  

/**
                 * 开始实例化bean.
                 */
                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                  //回调,会调用AbstractAutowireCapableBeanFactory的createBean方法。 return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }

 

  5.接着再次进入到createBean方法中.

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
     
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

     
     ............

try {//开始创建bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } }

 

 6.又进入到doCreateBean方法(这个方法很重要):

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //第1步,实例化对象,根据构造函数实例化对象。
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        /**
         * 根据是否是单例,是否允许循环依赖,当前对象是否在创建 三个条件。
         * 目的是将已经实例化的对象(还没有初始化)放入到一个对外可识别的容器中。
         */
        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        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");
            }
            /**
             * 将已经实例化的对象放入到singletonFactories,registeredSingletons 中。
             */
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //第二步,填充属性,解决依赖问题。
            populateBean(beanName, mbd, instanceWrapper);
            //调用initmethod方法,初始化。
            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) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    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 " +
                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

7.上述代码中有几个方法很重要: createBeanInstance,创建实例对象,就是调用构造函数,代码如下:  

return BeanUtils.instantiateClass(constructorToUse);

初始化对象完毕之后,只是在内存中分配了一块空地儿,对象中的属性全部都是null。

 

 

 8.那么接下来就需要进入到populateBean填充属性的方法中了,注意在填充属性之前,实例化之后,会做一个操作,将刚才实例化的TestDao(半成品只有内存空间,没有属性值)放到三级缓存中:

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            //半成品对象翻入三级缓存,提前曝光。
            if (!this.singletonObjects.containsKey(beanName)) { //一级缓存
                this.singletonFactories.put(beanName, singletonFactory); //三级缓存
                this.earlySingletonObjects.remove(beanName);    //二级缓存
                this.registeredSingletons.add(beanName);
            }
        }
    }

9.这个时候才会填充刚才已经实例化好的Testdao对象,进入到populateBean方法中,主要代码如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
     
           //获取bean的后置处理器,对已经实例化的bean做处理。if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        /**
                         * AutowiredAnnotationBeanPostProcessor 后置处理器处理属性依赖。
                         */
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }

10.这个时候再次进入到 postProcessPropertyValues 方法中发现进入到 InjectionMetadata的inject方法中,我们不妨先看看调用这个方法之前传入的参数:

 

 

 11.参数中的bean中的属性testservice依然为null,说明此时还没有注入,那么我们调试再进入到inject中,进入到这个方法中:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = this.checkedElements;
        Collection<InjectedElement> elementsToIterate =
                (checkedElements != null ? checkedElements : this.injectedElements);
      //获取到这个对象的所填充属性。 if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isDebugEnabled()) { logger.debug("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }

 

 

12. 通过上述接入可以看到TestDao 已经实例化,现在已经获取到他的一个属性类型为Testservice.

再次接着走入到 element.inject(target, beanName, pvs)方法中:

@Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

       ........else {
            Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                    descriptor, requestingBeanName);
            if (result == null) {//开始处理依赖
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            return result;
        }
    }

13.需要再次的进入到: doResolveDependency中:

@Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//开始处理依赖,处理基本类型,像Array,Map,Collection,
            Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) {
                return multipleBeans;
            }
            //根据属性匹配看有没有匹配的bean.
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) {
                if (isRequired(descriptor)) {
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                return null;
            }

            String autowiredBeanName;
            Object instanceCandidate;

            if (matchingBeans.size() > 1) {
                autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                    if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                        return descriptor.resolveNotUnique(type, matchingBeans);
                    }
                    else {
                        // In case of an optional Collection/Map, silently ignore a non-unique case:
                        // possibly it was meant to be an empty collection of multiple regular beans
                        // (before 4.3 in particular when we didn't even look for collection beans).
                        return null;
                    }
                }
                instanceCandidate = matchingBeans.get(autowiredBeanName);
            }
            else {
                // We have exactly one match.
                Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
                autowiredBeanName = entry.getKey();
                instanceCandidate = entry.getValue();
            }

            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(autowiredBeanName);
            }
            if (instanceCandidate instanceof Class) { //根据类型寻找daoBean定义之后,开始实例化这个bean.
                instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
            }
            Object result = instanceCandidate;
            if (result instanceof NullBean) {
                if (isRequired(descriptor)) {
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                result = null;
            }
            if (!ClassUtils.isAssignableValue(type, result)) {
                throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
            }
            return result;
        }
        finally {
            ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
        }
    }

14.我们注意到 findAutowireCandidates 这个方法好像是跟注解有关系的,先通过表达式看下结果:

 

 

 15.通过返回结果值看到时一个TestService 的class类,很明显这个方法是根据我传入的参数名称,从bean定义的容器中返回一个class对象,调试进去:

protected Map<String, Object> findAutowireCandidates(
            @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
      //这里根据传入的beanName = TestDao, requireType =com.audaque.learn.srvice.TestService
      //直接找到TestService这个bean.

String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); Map<String, Object> result = new LinkedHashMap<>(candidateNames.length); for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) { // Consider fallback matches if the first pass failed to find anything... DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty()) { // Consider self references as a final pass... // but in the case of a dependency collection, not the very same bean itself. for (String candidate : candidateNames) { if (isSelfReference(beanName, candidate) && (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } } } return result; }

16.这个方法主要代码就是第一行的

String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());从bean定义的容器中获取指定类型的bean.

 

 

 17.通过看参数返回值,发现已经返回了我们需要的testSerivce的定义对象,其实这里就是这个testService的beandefinition.

那么接下来已经获取到属性对应的bean定义信息了,那么就需要去实例化这个属性的bean了,代码会跳转到 descriptor.resolveCandidate这个方法中,

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
            throws BeansException {
    //别看只有一行代码,要了我的命,在这里再去实例化Testservice,流程跟实例化Testdao一样。
        return beanFactory.getBean(beanName);
    }

18.在通过一圈的调试,截图发现神奇的问题:

 

 

 先市实例化TestDao依赖TestService,那么会去实例化TestService,但是TestService中又依赖TestDao 的属性,但是现在截图中的效果是,TestService中的TestDao有值,但是TestDao中的属性值依然为空,说明在testservice实例化中已经从我们上边的某个地方获取到了TestDao,哈哈哈,是不是很神奇,写了半天了,才到了见证奇迹的时候了,其实我在第八步骤的时候,就有埋下伏笔的,在实例化TestDao 的时候,已经提前将这个半成品暴露出去了,那么在实例化Testservice的TestDao中获取,会从这个把这个半成品放到TestService 的testdao 属性上,不信?,代码如下:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
  //判断这个bean是否正在创建。 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) {
          //从二级缓存取。 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) {
          // 二级缓存没有,从三级缓存取。 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }

再结合第8步,是不是瞬间明白了?哈哈哈,不过没明白也没关系,我再来重新梳理一遍。

TestService依赖TestDao ,TestDao依赖TestService.

1.实例化TestDao,会调用getSingleton(),此时第一次调用返回空,那么就去实例化,并把返回结果TestDao放到三级缓存中,也就是singletonFactories中,并标注这个testDao的bean正在创建。

2.再去填充属性,发现有一个类型为TestService的属性,那么就会去实例化TestService这个对象。

3.实例化TestService这个对象,同样调用getSingleton()返回空,那么也要去实例化一个TestService对象,并把它放到singletonFactories三级缓存。

4.再去寻找TestService依赖的Testdao,这个时候调用getSingleton(),由于在第一步骤的时候已经放到缓存中,并且当前的属性testDao是在创建中,所有getSingleton()方法就会把第一部创建的对象返回。

5.TestService的属性填充完了。

6.开始再次返回到TestDao中将TestService设置到它本身的属性中。至此循环依赖就解决掉了。

*:通过这个分析其实并不是所有的循环依赖都能解决,我通过上述的过程分析可以看出来,属性之间的依赖是可以解决,构造函数与属性之间的依赖也是可以解决的,构造函数与构造函数之间的依赖是解决不了的。

 

标签:5.0,String,mbd,beanName,descriptor,bean,源码,null,第二集
来源: https://www.cnblogs.com/kangz/p/14208418.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有