spring源码解析之如何从spring中获取一个bean(总览)

前言:疫情期间,在家办公,虽说有种种不便,与此同时,也有了充足的时间,学习了一些想学习的知识,如有错误,敬请指出。

1:解读

spring的主要功能是IOC与AOP,此章节暂时不讲述AOP,但针对IOC来讲,getBean()方法是重中之重,例如下面这个例子,我们这样做就可以从容器中取出一个bean的实例

AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext(ProductServiceApplication.class);

configApplicationContext.getBean("test");

在整个spring源码之中,new AnnotationConfigApplicationContext(ProductServiceApplication.class)可以说初始化方法占据了极大的一部分,今天,不讲述初始化的过程,单纯从源码角度讲述getBean的工作流程

2:调用链说明

AnnotationConfigApplicationContext.getBean-->AbstractBeanFactory.getBean-->AbstractBeanFactory.doGetBean-->AbstractBeanFactory.getSingleton-->AbstractBeanFactory.createBean

上面是主要的流程,可以看出,getBean的真正获取,是在BeanFactory里面实现的,只不过AnnotationConfigContext里面有bean工厂的实例,最终的bean的创建是在beanFactory里面完成的

spring的方法命名规范也很有意思,几个getBean的方法其实没有做什么事情,最终是在doGetBean和getSignleton与createBean里面完成的。因此,代码解析在doGetBean(AbstractBeanFactory)开始。(由于电脑原因,down下来的spring源码已经丢了,只能看反编译过的代码,出入不大)

3:doGetBean解析

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        //获取bean的名称(因为存在FactoryBean,以后的博客再讲)
        final String beanName = this.transformedBeanName(name);
        //缓存,如果单例池中有的话就从单例池中获取,没有的话再创建,这个方法重要,解决循环依赖也是在这操作的
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            //如果缓存池中存在
            if (this.logger.isDebugEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        }
            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
               
                //又是一个重要的代码

                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

           } 
    }

与流程无关的代码已经被我删减了,可以看这些重要的代码。

(1):final String beanName = this.transformedBeanName(name);这主要是获取bean的一个名称,这么解释可能有些人有疑问了,不是我们getBean的时候已经把bean的名称传递进来了么,这么做的原因是因为存在一种特殊的bean(FactoryBean),之后会单开一讲专门讲解这个(很重要,一些三方框架例如mybatis与spring整合的时候就用到这个了)

(2):Object sharedInstance = this.getSingleton(beanName);主要是从单例池中获取bean,因为我们getBean获取的事单例模式的,所以假设我们之前创建过的时候不会重复创建,直接在单例池中取出来返回,而且这也是spring解决循环依赖的重要部分(不懂什么叫循环依赖的同学自行百度)

看下这块的代码逻辑

public Object getSingleton(String beanName) {
        return this.getSingleton(beanName, true);
    }

//参数allowEarlyReference的意思是是否允许提前创建,spring解决循环依赖就是通过允许提前创建一个实例来解决的

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //singletonObjects单例池对象,存储单例对象的一个map
        Object singletonObject = this.singletonObjects.get(beanName);
        
        //如果单例池中不存在&并且这个对象正在创建
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                //earlySingletonObjects(提前创建的bean的单例池)
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //还是空,beanFactory.getBean方法获取
                        singletonObject = singletonFactory.getObject();
                        //放入提前创建的单例池中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject != NULL_OBJECT ? singletonObject : null;
 }

getSignleton()方法的主要功能是看单例池中是否存在这个对象,存在返回,不存在则继续进行(关于earlySingletonObjects与singletonFactory可以暂时不用关注,结合后面内容一起理解)

(3):getSignleton(String beanName,ObjectFactory objectFacorty)注意区别下上面的getSingle方法,这里进入了BeanFactory真正创建单例对象的过程

sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                //这里是获取一个FactoryBean对象
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });

这其中应用到了好多后置处理器的地方,暂时不进行讲解,后面会抽时间呐出专门的篇章进行介绍后置处理器(Spring AOP功能就是利用后置处理器完成的)

进入getSignleton(beanName,FactoryBean factoryBean)方法内部

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized(this.singletonObjects) {
            //同样,先从缓存池中获取,没有再创建
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //将这个beanName加入singletonsCurrentlyInCreation集合里面(代表正在创建此对象)
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    //调用刚刚说的自己创建的FactoryBean进行创建对象
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //不用关注,校验

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    //如果是第一次创建这个对象,需要把这个对象加入到singletonObjects单例池,并且从singletonFactories与earlySingletonObjects移除他,这两个map的作用会在循环依赖中讲到
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject != NULL_OBJECT ? singletonObject : null;
        }
    }

总结下getSignleton(beanName,FactoryBean factoryBean)方法

【1】:单例缓存池中没有的话再创建

【2】:调用传进来的FactoryBean的getBean方法获取对象

【3】:创建末尾,将创建好的对象加入单例池,并且从singletonFactories与earlySinletonObjects中移除这个beanName。

重点关注【2】,我们在调用这个方法的时候自己创建了一个beanFactory并且,因此,创建的主要逻辑就在这里面了

sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                //这里是获取一个FactoryBean对象--创建对象的主要逻辑了
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });

(4):AbstractBeanFactory.createBean(beanName,mbd,args)【不重要的代码块已删除】

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        
        RootBeanDefinition mbdToUse = mbd;
        Object beanInstance;
        try {
            //这里本来想删除来,但是这里是实现代理的重要地方,利用后置处理器完成,暂时保留,但是不讲解,在获取bean的时候【没有代理的时候】没有用,可以忽略,等将后置处理器的时候再进行讲解
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
        }
        //又是相似的命名逻辑,createBean-->doCreateBean,真正操作的逻辑都是在do开头的方法里面
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    }

createBean里面又调用了doCreateBean,真正的逻辑再doCreateBean里面,方法命名形式眼熟不,(getSingleton-->doGetSingleton)

因此,我们到doCreateBean里面看下真正的操作(这个方法很复杂+重要,spring的后置处理器在这里体现的淋漓尽致)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
        //BeanWrapper 可以理解为bean的包装类,BeanWrapper我们可以获取到bean
        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null;
        Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null;
        mbd.resolvedTargetType = beanType;
        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //bean的后置处理器--暂时可以忽略
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }
        //判断我们这个bean是否可以被提前创建-说白了就是可以不可以被循环依赖
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }
            //如果可以循环依赖的话就把bean加入到singletonfactory中,之后单独拿出来写一下如何解决的循环依赖
            this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        Object exposedObject = bean;

        try {
            //属性注入,也是利用后置处理器完成的【又是一块很复杂且重要的代码】
            this.populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            }
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }
        //这里有代码,不重要,已删除

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

4:结语

以上,就是spring getBean的源码概览,挖了很多坑,例如,spring是如何解决循环依赖的;spring后置处理器如何操作,在getBean的过程中如何在哪里有应用后置处理器;spring如何进行属性注入【其实也是利用后置处理器】;再进一步,spring aop是怎么实现的【也是在getBean这个实现的】。接下来的一段时间,会慢慢把这些坑给填上的~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章