• spring源码分析之玩转ioc:bean初始化和依赖注入(一)


        最近赶项目,天天加班到十一二点,终于把文档和代码都整完了,接上继续整。

        上一篇聊了beanProcess的注册以及对bean的自定义修改和添加,也标志着创建bean的准备工作都做好了,接下来就是开大招的时候了:

        首先看org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization,refresh()方法的倒数第二个方法:

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            // Initialize conversion service for this context.
            if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                    beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
                beanFactory.setConversionService(
                        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
            }
    
            // Register a default embedded value resolver if no bean post-processor
            // (such as a PropertyPlaceholderConfigurer bean) registered any before:
            // at this point, primarily for resolution in annotation attribute values.
            if (!beanFactory.hasEmbeddedValueResolver()) {
                beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
            }
    
            // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
            String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
            for (String weaverAwareName : weaverAwareNames) {
                getBean(weaverAwareName);
            }
    
            // Stop using the temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(null);
    
            // Allow for caching all bean definition metadata, not expecting further changes.
            beanFactory.freezeConfiguration();
    
            //主要看这里(实例化所有剩下的非懒加载的单例bean)
            // Instantiate all remaining (non-lazy-init) singletons.
            beanFactory.preInstantiateSingletons();
        }

    主要看最后一个方法,点进去:

    可以看到getBean()方法,继续往下点:getBean()  -->  doGetBean:

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
            final String beanName = transformedBeanName(name);
            Object bean;
    
            // Eagerly check singleton cache for manually registered singletons.
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) {
                if (logger.isTraceEnabled()) {
                    if (isSingletonCurrentlyInCreation(beanName)) {
                        logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                                "' that is not fully initialized yet - a consequence of a circular reference");
                    }
                    else {
                        logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                    }
                }
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
    
            else {
                // Fail if we're already creating this bean instance:
                // We're assumably within a circular reference.
                if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
    
                // Check if bean definition exists in this factory.
                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                    // Not found -> check parent.
                    String nameToLookup = originalBeanName(name);
                    if (parentBeanFactory instanceof AbstractBeanFactory) {
                        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                                nameToLookup, requiredType, args, typeCheckOnly);
                    }
                    else if (args != null) {
                        // Delegation to parent with explicit args.
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else if (requiredType != null) {
                        // No args -> delegate to standard getBean method.
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                    else {
                        return (T) parentBeanFactory.getBean(nameToLookup);
                    }
                }
    
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
    
                try {
                    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    checkMergedBeanDefinition(mbd, beanName, args);
    
                    // Guarantee initialization of beans that the current bean depends on.
                    String[] dependsOn = mbd.getDependsOn();
    //判断是否配置dependsOn
    if (dependsOn != null) {
    //这个很明显,告诉我们一个bean可以配置多个,
    for (String dep : dependsOn) {
    //校验是否存在循环依赖
    if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try {
    //重新走bean生成流程,其实就是先去实例化dependsOn的备案 getBean(dep); }
    catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { 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); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); 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; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }

    主要看try-catch包住的代码,首先看第一步,首先看dependsOn是否配置,其实就是@DependOn注解配置,如果配置了这边就需要先去加载dependOn配置的类,这个功能其实很实用,我们经常在spring加载的时候,有一些bean的加载需要依赖其他bean的属性,那么这个时候,就需要用到这个了,说完用法,再看看这边具体做了什么:

      1.判断是否配置dependsOn

      2.遍历dependsOn的bean

     2.1 判断是否存在循环依赖

     2.2 获取bean

    单例的话就是走单例bean实例化:首先需要创建bean,看createBean()  -->  doCreateBean() 

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
                throws BeanCreationException {
    
            // Instantiate the bean.
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
            final 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.isTraceEnabled()) {
                    logger.trace("Eagerly caching bean '" + beanName +
                            "' to allow for resolving potential circular references");
                }
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                populateBean(beanName, mbd, instanceWrapper);
                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 " +
                                    "'getBeanNamesOfType' 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;
        }

    我们平时用的bean绝大部分都是单例的,所以这块是我们平时用到的最多的。

    1. createBeanInstance

    抛开一些判断,我们先看determineConstructorsFromBeanPostProcessors(beanClass, beanName):

    protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
                throws BeansException {
    
            if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                        Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                        if (ctors != null) {
                            return ctors;
                        }
                    }
                }
            }
            return null;
        }

    这块做的很简单:遍历beanProcessor,调用所有是SmartInstantiationAwareBeanPostProcessor类型的determineCandidateConstructors方法:

    主要看org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors(因为其他都没有具体业务逻辑return null)

    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
                throws BeanCreationException {
    
            // Let's check for lookup methods here..
            if (!this.lookupMethodsChecked.contains(beanName)) {
                try {
                    ReflectionUtils.doWithMethods(beanClass, method -> {
                        Lookup lookup = method.getAnnotation(Lookup.class);
                        if (lookup != null) {
                            Assert.state(this.beanFactory != null, "No BeanFactory available");
                            LookupOverride override = new LookupOverride(method, lookup.value());
                            try {
                                RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
                                mbd.getMethodOverrides().addOverride(override);
                            }
                            catch (NoSuchBeanDefinitionException ex) {
                                throw new BeanCreationException(beanName,
                                        "Cannot apply @Lookup to beans without corresponding bean definition");
                            }
                        }
                    });
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
                }
                this.lookupMethodsChecked.add(beanName);
            }
    
            // Quick check on the concurrent map first, with minimal locking.
            Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            if (candidateConstructors == null) {
                // Fully synchronized resolution now...
                synchronized (this.candidateConstructorsCache) {
                    candidateConstructors = this.candidateConstructorsCache.get(beanClass);
                    if (candidateConstructors == null) {
                        Constructor<?>[] rawCandidates;
                        try {
                            rawCandidates = beanClass.getDeclaredConstructors();
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                                    "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                        }
                        List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
                        Constructor<?> requiredConstructor = null;
                        Constructor<?> defaultConstructor = null;
                        Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
                        int nonSyntheticConstructors = 0;
                        for (Constructor<?> candidate : rawCandidates) {
                            if (!candidate.isSynthetic()) {
                                nonSyntheticConstructors++;
                            }
                            else if (primaryConstructor != null) {
                                continue;
                            }
                            AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                            if (ann == null) {
                                Class<?> userClass = ClassUtils.getUserClass(beanClass);
                                if (userClass != beanClass) {
                                    try {
                                        Constructor<?> superCtor =
                                                userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                        ann = findAutowiredAnnotation(superCtor);
                                    }
                                    catch (NoSuchMethodException ex) {
                                        // Simply proceed, no equivalent superclass constructor found...
                                    }
                                }
                            }
                            if (ann != null) {
                                if (requiredConstructor != null) {
                                    throw new BeanCreationException(beanName,
                                            "Invalid autowire-marked constructor: " + candidate +
                                            ". Found constructor with 'required' Autowired annotation already: " +
                                            requiredConstructor);
                                }
                                boolean required = determineRequiredStatus(ann);
                                if (required) {
                                    if (!candidates.isEmpty()) {
                                        throw new BeanCreationException(beanName,
                                                "Invalid autowire-marked constructors: " + candidates +
                                                ". Found constructor with 'required' Autowired annotation: " +
                                                candidate);
                                    }
                                    requiredConstructor = candidate;
                                }
                                candidates.add(candidate);
                            }
                            else if (candidate.getParameterCount() == 0) {
                                defaultConstructor = candidate;
                            }
                        }
                        if (!candidates.isEmpty()) {
                            // Add default constructor to list of optional constructors, as fallback.
                            if (requiredConstructor == null) {
                                if (defaultConstructor != null) {
                                    candidates.add(defaultConstructor);
                                }
                                else if (candidates.size() == 1 && logger.isInfoEnabled()) {
                                    logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
                                            "': single autowire-marked constructor flagged as optional - " +
                                            "this constructor is effectively required since there is no " +
                                            "default constructor to fall back to: " + candidates.get(0));
                                }
                            }
                            candidateConstructors = candidates.toArray(new Constructor<?>[0]);
                        }
                        else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
                            candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
                        }
                        else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
                                defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
                            candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
                        }
                        else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
                            candidateConstructors = new Constructor<?>[] {primaryConstructor};
                        }
                        else {
                            candidateConstructors = new Constructor<?>[0];
                        }
                        this.candidateConstructorsCache.put(beanClass, candidateConstructors);
                    }
                }
            }
            return (candidateConstructors.length > 0 ? candidateConstructors : null);
        }

    1.首先处理LookUp注解,加到beandefinition容器override属性管理

    2.获取bean对应的构造器beanClass.getDeclaredConstructors();

    3.AnnotationAttributes ann = findAutowiredAnnotation(candidate); 获取bean的构造函数上面@Autowried注解信息。

    4.返回有@Autowried注解的构造函数数组

    其实这块一般不需要知道很细节,只是获取@Autowried在构造函数上的信息,经常都可能是不走这块的,毕竟我们一般用的多的无参构造bean。

    再看默认无参构造函数是如何实例化的:

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
            // Don't override the class with CGLIB if no overrides.
            if (!bd.hasMethodOverrides()) {
                Constructor<?> constructorToUse;
                synchronized (bd.constructorArgumentLock) {
                    constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                    if (constructorToUse == null) {
                        final Class<?> clazz = bd.getBeanClass();
                        if (clazz.isInterface()) {
                            throw new BeanInstantiationException(clazz, "Specified class is an interface");
                        }
                        try {
                            if (System.getSecurityManager() != null) {
                                constructorToUse = AccessController.doPrivileged(
                                        (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                            }
                            else {
                                constructorToUse = clazz.getDeclaredConstructor();
                            }
                            bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                        }
                        catch (Throwable ex) {
                            throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                        }
                    }
                }
                return BeanUtils.instantiateClass(constructorToUse);
            }
            else {
                // Must generate CGLIB subclass.
                return instantiateWithMethodInjection(bd, beanName, owner);
            }
        }

    这块大致看一下,也就是反射直接去拿。这时候不管是无参还是有参都已经拿到实例了(这里是BeanWrapper对象)。

    接下来会调用applyMergedBeanDefinitionPostProcessors方法,核心最终会调用到org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition和org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition,有兴趣的可以研究一下,其实做的事情都是类似的:

    1.收集@Autowried@Value@PostConstruct@PreDestroy等注解,

    2.将注解对应的method对象封装成LifeCycleElement对象

    3.对象封装到容器中

    实例化完成就需要初始化了,在这之前会先判断是否允许循环依赖,如果可以,那么先把bean放到singletonFactories,earlySingletonObjects,registeredSingletons三大容器当中。

    初始化首先需要属性赋值:populateBean(beanName, mbd, instanceWrapper):

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
            if (bw == null) {
                if (mbd.hasPropertyValues()) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
                }
                else {
                    // Skip property population phase for null instance.
                    return;
                }
            }
    
            // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
            // state of the bean before properties are set. This can be used, for example,
            // to support styles of field injection.
            boolean continueWithPropertyPopulation = true;
    
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                            continueWithPropertyPopulation = false;
                            break;
                        }
                    }
                }
            }
    
            if (!continueWithPropertyPopulation) {
                return;
            }
    
            PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    
            if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
                // Add property values based on autowire by name if applicable.
                if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
                    autowireByName(beanName, mbd, bw, newPvs);
                }
                // Add property values based on autowire by type if applicable.
                if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                    autowireByType(beanName, mbd, bw, newPvs);
                }
                pvs = newPvs;
            }
    
            boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    
            PropertyDescriptor[] filteredPds = null;
            if (hasInstAwareBpps) {
                if (pvs == null) {
                    pvs = mbd.getPropertyValues();
                }
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            if (filteredPds == null) {
                                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                            }
                            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                            if (pvsToUse == null) {
                                return;
                            }
                        }
                        pvs = pvsToUse;
                    }
                }
            }
            if (needsDepCheck) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
    
            if (pvs != null) {
                applyPropertyValues(beanName, mbd, bw, pvs);
            }
        }

     好像又写的很多了,bean初始化的东西有点多,population方法包含了核心的ioc和di,想了想还是放到下一章写吧。

    总结:

        之前看源码的时候,思路理清楚了,说也能说的出来,但是到自己写的时候,发现很多细节用文字去表达,总觉得表达的有所欠缺,总是觉得有更好的词汇去描述。

      spring源码的逻辑还是蛮复杂的,看过mybatis,dubbo,zk等框架的源码,一开始觉得spring的没那么难,毕竟网上的博客啥的太多了,但是其实看的越多,越觉得很多东西不是不难,而是自己根本都没有以自己的思想去看,看完了,其实还是站在别人思考的角度去看待,也局限于别人的思维,欠缺的还是很多啊!

  • 相关阅读:
    使用Jenkins自带功能(不用shell)构建Docker镜像并推送到远程仓库
    方法2:使用Jenkins构建Docker镜像 --SpringCloud
    在jenkins中使用shell命令推送当前主机上的docker镜像到远程的Harbor私有仓库
    解决跟Docker私有仓库登陆,推送,拉取镜像出现的报错
    Linux 内存占用大排查
    方法1:使用Jenkins构建Docker镜像 --SpringCloud
    使用Jenkins编译打包SpringCloud微服务中的个别目录
    使用Jenkins的Git Parameter插件来从远程仓库拉取指定目录的内容
    稀疏检出-使用git检索出仓库里的某一个目录文件,而不是整个仓库的所有文件
    通过 Kubeadm 安装 K8S 与高可用,版本1.13.4
  • 原文地址:https://www.cnblogs.com/gmt-hao/p/13132334.html
Copyright © 2020-2023  润新知