Spring IoC - dependency injection

undefined

Foreword

The previous article, we introduced the Spring IoC container initialization - IoC container initialization

In this article, we continue to introduce Spring IoC dependency injection process and source code interpretation.

Or as before, as we comb-step process, in order to have a general context in mind to everyone, source code easier to read and easier to seize the key.

main content:

  • beanName analysis and conversion
  • Manual registration detection Bean
  • Parents vessel detection
  • Dependent initialization (recursively)
  • ★ create a singleton instance
    • Object instantiation
    • Properties assembly
    • Various callback events after treatment Bean Creation
  • ...

Source resolve

Finally a last chapter, the initialization container penultimate step, finishBeanFactoryInitialization(beanFactory)instantiate all single embodiment, calls getBean()the method to do the operation example of singleton bean. This is the Spring IoC dependency injection inlet.

Before you begin, there is little need to mention. We are in front of the vessel after the initialization from coming in, but the actual operation, we may be in the normal operation of the program, with ApplicationContext.getBean()to acquire container bean. Do not just limited to the perspective of.

Now let's get started.

First lookgetBean()

Source Location:AbstractBeanFactory#getBean(String name)

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }复制代码

doGetBean()

deGetBean()

  • beanName analysis and conversion
  • Manual registration detection Bean
  • Parents vessel detection
  • Dependent initialization (recursively)
  • Creating Bean createBean()
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        // 反正就是获取到真正beanName
        // 处理两个情况,1. 将别名转化成真的beanName;2. 把FactoryBean的前缀"&"给去了
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        // 检测已经注册的Bean,保证不重复创建
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 这个方法还是有点逻辑的
            // 如果目前获得的sharedInstance 不是FactoryBean,那bean就赋值成sharedInstance,直接返回
            // 如果是FactoryBean就返回FactoryBean创建的实例,
            // 这个也是FactoryBean的知识点,我在我的另一篇文章也讲过了,
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // 直接翻译:创建过了此 beanName 的 prototype 类型的 bean,那么抛异常
            // We're assumably within a circular reference.
            // 往往是因为陷入了循环引用
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            // 检查下这个BeanDefinition是否存在
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                // 当前容器没有这个BeanDefinition,去parent 容器去找
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                // 这个 getMergedLocalBeanDefinition 前面讲过哦
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 先初始化依赖的所有 Bean,这个很好理解。
                // 注意,这里的依赖指的是 depends-on 中定义的依赖
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            // 这里循环依赖概念不要紊乱了
                            // 这里指的是通过 depends-on 定义造成的循环依赖,
                            // 我们另外一种类成员式的循环引用Spring是支持的
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 注册依赖关系
                        // 这么做的原因是Spring在即将进行bean销毁的时候会【首先销毁被依赖的bean】。
                        // 看SpringBean的初始化和销毁顺序就知道了,依赖关系的保存目的就是这个
                        // 依赖关系的保存是通过一个ConcurrentHashMap<String, Set>完成的,key是bean的真实名字。
                        registerDependentBean(dep, beanName);
                        try {
                            // 先去初始化被依赖项
                            // 递归然后反递归回来
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // Create bean instance.
                // 如果是 singleton scope 的,创建 singleton 的实例
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                // 创建Bean的详情,等下拉出来单独说
                                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);
                }

                // 如果是 prototype scope 的,创建 prototype 的实例
                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);
                }

                // 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
                // 这里非重点,我们的重点是singleton的创建
                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, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                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 && bean != null && !requiredType.isInstance(bean)) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }复制代码

doCreateBean ()

Overview of steps:

  1. Began as a single case, then the first clear the cache;
  2. Examples of the bean, to convert the BeanWrapper BeanDefinition;
  3. Use MergedBeanDefinitionPostProcessor, Autowired annotation is achieved by this type of pre-parsing method;
  4. Resolve circular dependencies;
  5. Filling properties into the bean filled property instance;
  6. Registration DisposableBean;
  7. Creating complete and return

Three concerns:

  1. createBeanInstance () to instantiate
  2. populateBean (); assembling property
  3. initializeBean () callback event after various initialization processing Bean
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        // 这个BeanWrapper是创建出来持有对象的
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            // 如果是singleton,先把缓存中的同名bean消除
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) 
            // 关键代码,后面拉出来单独讲
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;

        // Allow post-processors to modify the merged bean definition.
        // 涉及接口:MergedBeanDefinitionPostProcessor
        // 不是关键逻辑,不讲了
        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.
        // 这里是为了解决循环依赖的,先把初步实例化的Bean实例的引用缓存起来,暴露出去,
        // 这个可以结合别的文章学习,面试题常考,我后面可能也会写
        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");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            // 时序图中的一步,关键步骤,属性装配,前面的实例只是实例化,没有装配属性
            // 和前面的createBeanInstance一样会拉出来讲,继续看下去吧
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                // 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
                 // 这里就是处理 bean 初始化完成后的各种回调
                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);
            }
        }


        // 这个逻辑分支我一次性说完吧。
        // 如果该beanName对象已经注册单例模式,则从单例中获取,并判断获取到的bean实例(B)与BeanWrapper中的bean实例(A)是同一个实例,如果是,则返回A或者B,如果不是,则递归找出它的依赖bean。
        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
             // earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    // 两个是同一个引用,bean初始化完成
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(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.
        // 注册DisposableBean;
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }
复制代码

Previous concerns three separate terms.

1. createBeanInstance()

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        // Make sure bean class is actually resolved at this point.
        // 解析出 Class
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        // 如果工厂方法不为空,则是用工厂方法初始化
        if (mbd.getFactoryMethodName() != null)  {
            // 相关知识点看另一篇文章关于FactoryBean的
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        // 如果不是第一次创建,比如第二次创建 prototype bean。
           // 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
        // 所以注释说叫shortcut
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    // 有已经解析过的构造方法
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        // 如果已经解析过则使用解析好的构造方法不需要再次锁定
        if (resolved) {
            if (autowireNecessary) {
                // 构造方法自动注入
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 默认构造方法
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
        // 判断是否采用有参构造函数
        // 构造器自动装配
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        // 使用无参构造器
        return instantiateBean(beanName, mbd);
    }
复制代码

2. populateBean (); assembling property

Method AbstractAutowireCapableBeanFactory#populateBeaninlet: ,

Its role is: autowire according to the type autowire by name, by typeeither directly set

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        if (bw == null) {
            if (!pvs.isEmpty()) {
                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.
        // 这里看注解是一个扩展点 
        // InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改
        // 不是个常用的扩展点,这里不讲了
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            // 通过类型装配
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        // InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法
                        // 代表能对属性值进行修改的能力
                        // 其中一个很有用实现类提一下,AutowiredAnnotationBeanPostProcessor
                        // 对采用@Autowired和@Value设值的就是这个BeanPostProcessor干的。
                        // 不展开讲了,不然要讲不完了
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
        // 这里才是设置bean实例的属性值
        applyPropertyValues(beanName, mbd, bw, pvs);
    }复制代码

3. initializeBean () callback event after various initialization processing Bean

Look javadoc description of this method

Initialize the given bean instance, applying factory callbacks as well as init methods and bean post processors.

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            // 涉及到的回调接口点进去一目了然,代码都是自解释的
            // BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessBeforeInitialization 回调
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // init-methods
            // 或者是实现了InitializingBean接口,会调用afterPropertiesSet() 方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessAfterInitialization 回调
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }复制代码

We find no, two callbacks BeanPostProcessor have taken place here, but the middle of processing the init-method. This is my original perception a bit different? Because the name of the source code of Spring often are self-explanatory, many times I see that the English knew the intent of these methods, but here's why the pre-processing method BeanPostProcessor postProcessBeforeInitialization()also set the property after the completion of the call?

Queries to see the back of the interpretation in English,

BeanPostProcessor is used to interact with newly created bean instances before and/or after their initialization method is invoked by the Spring container. You can use BeanPostProcessor to execute custom logic before and/or after bean’s initialization method is invoked by the Spring container.

BeanPostProcessor intent is to do before and after the initialization method of customization operations. Think about it as if the name did wrong. If it is called before SpringBean instantiation it should be called BeforeInstantiation. The source code initializationrefers to the above invokeInitMethodsoperation.

Epilogue

Above, it is the main content on Spring IoC dependency injection.

Spring IoC container There are other points of knowledge, about SpringIoC characteristics. For example, Spring bean life cycle, FactoryBean, BeanPostProcessor, are using Spring IoC container properties often encountered. In the understanding of the overall operation principle IoC container later, you should be able to analyze some of these features, the method you use to combine these features and source code, in context.

So far, Spring IoC dependency injection with regard to the source "approximately" interpretation is completed, then again, the above source code parsing, certainly not complete, but I think the extracted important things.

If omissions, please understand and learn their own access to relevant information. If an error, please correct me!

This article from the blog article multiple platforms OpenWrite release!

Guess you like

Origin juejin.im/post/5da7a0555188257a7306822d