Spring 之 BeanFactory 源码 - 抽象/类 分析

BeanFactory的基本类体系结构(类为主):

  上图可与 Spring源码分析——BeanFactory体系之接口详细分析 的图结合分析,一个以接口为主,一个以类为主

具体:

  1、7层的类体系继承。

  2、AbstractBeanFactory实现了最重要的ConfigurableBeanFactory接口,DefaultSingletonBeanRegistry实现了SingletonBeanRegistry单例类注册接口,SimpleAliasRegistry实现了AliasRegistry别名注册接口。

  3、祖先类SimpleAliasRegistry、DefaultSingletonBeanRegistry和子孙类XmlBeanFactory、DefaultListableBeanFactory是完整的类,而中间的类FactoryBeanRegistrySupport、AbstractBeanFactory、AbstractAutowireCapableBeanFactory都是抽象类。

总结:

  具体上来说,XmlBeanFactory光是父类就有6个了,加上自身,总共7层了。实际上分析接口结构就会看到,作为IOC类工厂而言,XmlBeanFactory的类体系结构实际是从祖先AbstractBeanFactory这个类开始的,因为是它实现了BeanFactory的子接口ConfigurableBeanFactory,虽然它继承自FactoryBeanRegistrySupport,但可以说这只是工厂功能的扩充,扩展了对工厂Bean以及工厂所产生的Bean的操作。

简单的别名注册器——SimpleAliasRegistry

  上篇已经讲过AliasRegistry,非常简单的4个方法,体现了对别名注册的支持,而SimpleAliasRegistry就是它的简单实现。

源码:

  View Code

 具体:

  1、1个支持高并发的ConcurrentHashMap来放置所有的别名,其中key是别名,value是真名。

  2、4个方法实现了SimpleAliasRegistry。

  3、3个用来辅助实现4个接口方法的方法。其中canonicalName(String name)的实现非常优雅,用来循环来回判断,把aliasMap中无对应值的key返回。

  4、2个添加额外功能的方法 retrieveAliases 和 resolveAliases ,前者是找出名字对应的所有别名,后者是用一个StringValueResolver处理解析所有的别名-名称。

总结:

  这是一个非常简单的别名注册器,一个简单的接口实现。不过其中包含了非常优雅的方法实现,值得一看!

默认单例注册类——DefaultSingletonBeanRegistry

源码:  

  View Code

具体:

  1、一个静态不可变的空对象NULL_OBJECT、一个简单的日志对象。

  2、本类有如下集合:

    (1)、一个单例缓存集合——singletonObjects

    (2)、一个单例工厂缓存集合——singletonFactories

    (3)、一个早期单例对象缓存集合——earlySingletonObjects

    (4)、一个注册过的单例类(单例工厂)集合——registeredSingletons

    (5)、一个即将创建的单例类集合——singletonsCurrentlyInCreation

    (6)、一个正在创建的单例类集合——inCreationCheckExclusions

    (7)、一个被压制的异常集合——suppressedExceptions(这种设计模式实在是经典!)

    (8)、一个判断所有单例类是否马上被销毁的标记——singletonsCurrentlyInDestruction

    (9)、一个Disposable接口(即可以自定义回收资源的接口)实例的集合——disposableBeans

    (10)、一个bean名称和bean所有包含的Bean的名称的集合——containedBeanMap

    (11)、bean名称和所有依赖于Bean的名称的集合——dependentBeanMap

    (12)、bean名称和bean所依赖的所有名称的集合——dependenciesForBeanMap

  3、2个注册单例方法,实际是暴露在外的SingletonBeanRegistry接口的实现方法registerSingleton加锁后调用另一个addSingleton方法。

  4、1个注册单例工厂的方法。单例工厂类不能和单例类同名。

  5、3个获取单例类的方法。一种是从单例类集合中获取,如果获取不到,boolean控制要么返回空对象,要么返回一个单例工厂。另一种是从单例集合中获取,如果取不到,就从指定的工厂中获取。还有一种?呵,就是暴露在外的SingletonBeanRegistry接口方法呗,直接调用第一种。

  6、1个添加被压制的异常集合中添加异常的方法,我觉得这个设计非常经典。但需要记录异常,却不想处理的时候,可以采用这种设计模式。

  7、1个移除单例的方法、1个判断是否包含单例的方法、1个返回所有单例名数组的方法、1个返回单例总数目的方法。

  8、1个设置某个Bean是否正在创建的方法、1个判断某个Bean是否正在被创建的方法、2个判断某个Bean是否即将被创建的方法(一个调用另一个,用于重写)。

  9、1个单例类创建开始之前调用的方法、1个单单例类创建之后调用的方法

  10、1个往Disposable实例集合注册Disposable实例的方法,这个是Bean销毁前的准备。

  11、1个注册一个被包含的Bean和一个包含的Bean的名称到containedBeanMap集合的方法。这个方法设置了Bean之间的包含关系。

  12、1个给指定的Bean注册一个其依赖的Bean的方法。这个方法设置了Bean自己的依赖关系。

  13、1个判断是否被依赖的方法、1个返回给定Bean名称的所有依赖的数组的方法、1个返回依赖于给定Bean的所有Bean名的数组的方法。

  14、1个销毁所有单例类的方法(这个方法居然完全没有注释,有没搞错!)、1个销毁某个单例的方法、1个// 销毁指定名称的Bean,且销毁依赖于它的所有Bean的方法。

  15、1个返回子类单例类的互斥体的方法。这个暂且待下一篇分析子类再看。

总结:

  类如其名,默认的单例注册器。这个工厂的写法实在功能丰富,为了监控到一个单例类构建过程中的方方面面,简直就是不择手段啊,居然准备了12个集合,除了一个一个被压制的异常集合,其余全是跟单例类有直接关系的。可以说,这个单例注册器监听、实现了Spring单例注册的各个过程,具体的解读分析,在上面的源代码中可以看到,读者阅读我注释过的源代码应该会很轻松。

 

工厂Bean注册支持——FactoryBeanRegistrySupport

废话不多说,直接看我注释的源码:

  View Code

具体:

  1、1个不可变的实例属性ConcurrentHashMap来存放工厂Bean生产的单例的集合:FactoryBean name --> object。

  2、1个方法返回指定FactoryBean的类型的方法。

  3、1个根据FactoryBean名,返回其生产的Object的方法。

  4、2个从工厂Bean中取实例的方法。实际是一个方法调用另一个,取不到则返回空。

  5、1个postProcessObjectFromFactoryBean的方法,留给子类重写。

  6、1个取工厂Bean的方法——如果这个Object是FactoryBean类型,就转换成FactoryBean返回

  7、1个重写父类的removeSingleton方法,移除单例的时候,父类的移除之外,还要移除factoryBeanObjectCache中的。

  8、1个返回当前容器的安全访问上下文的方法。

总结:

  这个类FactoryBeanRegistrySupport,类如其名,实现了对工厂Bean注册的支持。值得注意的是,这个类有较多类似如下的写法:

复制代码
    if (System.getSecurityManager() != null) {//如果当前系统存在安全管理器
                return AccessController.doPrivileged(new PrivilegedAction<Class>() {
                    public Class run() {
                        //实际处理
                    }
                }, getAccessControlContext());
            }
            else {//不存在安全管理器,就直接调用!
                //实际处理
            }        
复制代码

  这个方法的意思是,如果当前系统存在安全管理器,那么接下来的操作不做权限检查,直接调用。而如果不存在,OK,那当然是直接调用了。这是JDK层面的一个系统安全管理工具,某些情况下,可以避免系统进行安全检查。这里稍作了解即可。在学习JVM的时候可仔细了解原理。

  除此之外,这里可以了解一下这个类比较重要的方法doGetObjectFromFactoryBean,是从工厂Bean中取实例的方法,源码已经给出,这里重点指出一下,不必折叠了:

复制代码
//从工厂Bean中取实例,shouldPostProcess指的是是否允许提前处理
    private Object doGetObjectFromFactoryBean(
            final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
            throws BeanCreationException {

        Object object;
        //跟getTypeForFactoryBean的实现一样。
        try {
            if (System.getSecurityManager() != null) {//若系统存在安全管理器
                AccessControlContext acc = getAccessControlContext();//得到当前容器的安全访问上下文
                try {//返回factoryBean的类型这个操作不做权限检查,直接调用
                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        public Object run() throws Exception {
                                return factory.getObject();
                            }
                        }, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {//否则直接取
                object = factory.getObject();
            }
        }
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }

        //如果从beanFactory取不到,且这个实例即将被创建,抛出异常
        if (object == null && isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        //若取不到,并非即将创建、且这个实例允许前处理
        if (object != null && shouldPostProcess) {
            try {
                object = postProcessObjectFromFactoryBean(object, beanName);//这里简单返回,前处理的功能留给子类重写
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
            }
        }

        return object;
    }
复制代码

  相信上面已经解释的很清楚了。

最重要的抽象类——AbstractBeanFactory

  (PS:这个类的方法实在是多的骇人,看得我实在是头都大了。不多看到后面,发现很多方法其实也就是那么回事。源码注释了大部分,且看看咯!)

  View Code

  总结:方法太多了,一个个介绍很浪费时间,不具体介绍。大体介绍一下吧。这个AbstractBeanFactory继承了支持工厂Bean注册的FactoryBeanRegistrySupport,并且实现了BeanFactory重要的第三级接口——ConfigurableBeanFactory。需要具体了解这个接口,可以去看我之前的接口分析——Spring源码分析——BeanFactory体系之接口详细分析 。ConfigurableBeanFactory是一个非常复杂的接口,继承了HierarchicalBeanFactory和SingletonBeanRegistry,主要实现了工厂创建、注册Bean、单例类注册等各种功能。

  AbstractBeanFactory实现了ConfigurableBeanFactory接口的绝大多数方法,实现了Bean工厂的许多重要功能,如BeanDefinition、RootBeanDefinition、原型、单例相关的各种操作。

  下面列出一些主要方法实现,其他的方法说明,可具体参照上文我贴出的大部分注释过的源码。

(1)、从容器中获取bean的方法——doGetBean:

复制代码
@SuppressWarnings("unchecked")
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        final String beanName = transformedBeanName(name);//在aliasMap中取得的标准名
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);//首先在单例集合中取
        if (sharedInstance != null && args == null) {//如果取得到,没有指定参数
            if (logger.isDebugEnabled()) {//若Log允许调试
                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 + "'");
                }
            }
            ////根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            if (isPrototypeCurrentlyInCreation(beanName)) {//如果正在被创建,就抛出异常
                throw new BeanCurrentlyInCreationException(beanName);
            }

            BeanFactory parentBeanFactory = getParentBeanFactory();//取本容器的父容器
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//若存在父容器,且本容器不存在对应的Bean定义
                String nameToLookup = originalBeanName(name);//取原始的Bean名
                if (args != null) {//若参数列表存在
                    // 那么用父容器根据原始Bean名和参数列表返回
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // 参数列表不要求,那就直接根据原始名称和要求的类型返回
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            //如果不需要类型检查,标记其已经被创建
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            //根据beanName取其根Bean定义
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            String[] dependsOn = mbd.getDependsOn();//得到这个根定义的所有依赖
            if (dependsOn != null) {
                for (String dependsOnBean : dependsOn) {
                    getBean(dependsOnBean);//注册这个Bean
                    //注册一个Bean和依赖于它的Bean(后参数依赖前参数)
                    registerDependentBean(dependsOnBean, beanName);
                }
            }

            // 如果Bean定义是单例,就在返回单例
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                //根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
                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 '" + scopeName + "'");
                }
                try {//根据范围创建实例
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);//原型创建前,与当前线程绑定
                            }
                            finally {
                                ////原型创建后,与当前线程解除绑定
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    //根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
                    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);
                }
            }
        }

        //判断要求的类型是否和Bean实例的类型正在匹配
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            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;
    }
复制代码

下面对这个方法进行简要的解释:

  <1>、这个方法形参为final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly,分别表示Bean的名称、要求返回的Bean的类型、取Bean时提供的参数数组 以及 是否需要类型检查。哦

  <2>、final String beanName = transformedBeanName(name); 这个方法是从aliasMap中取得对应的标准名。方法实现是,首先去掉name的 FACTORY_BEAN_PREFIX 前缀(如果是工厂Bean本身,那么Bean名有这个前缀),然后调用SimpleAliasRegistry的canonicalName方法。上篇博客已经介绍过SimpleAliasRegistry了,这里贴一下这个方法的源码:

复制代码
/*
     * 根据name这个Key,在aliasMap中不断循环的取对应的value,如果取得到,就继续根据这个value取值,不断循环继续。
     * 直到取不到,就把这个在aliasMap中无对应值的key返回。这个动作,叫规范名
     */
    public String canonicalName(String name) {
        String canonicalName = name;    //规范名
        // Handle aliasing...
        String resolvedName;//已解析名
        do {
            resolvedName = this.aliasMap.get(canonicalName);//aliasMap中规范名对应的值赋值给已解析名
            if (resolvedName != null) {//如果已解析名存在(即规范名在aliasMap中有对应的值)
                canonicalName = resolvedName;   // 这个已解析名赋值给标准名
            }
        } while (resolvedName != null);//不断循环,直到已解析名不存在
        return canonicalName;
    }
复制代码

  <3>、首先根据标准名beanName,在单例缓存中取对应的Bean:Object sharedInstance = getSingleton(beanName);

  <4>、如果取得到,且args为空,根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例:bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);然后结束整个方法。这个方法源码如下:

复制代码
//根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

        //如果这个Bean是工厂Bean创建的 且 这个Bean实例并不是FactoryBean实例,抛异常
        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }

        //如果这个Bean实例并不是FactoryBean实例 或 这个Bean是工厂Bean创建的,直接返回
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

        //——————————以下都是 这个Bean实例是FactoryBean实例的情况
        Object object = null;
        if (mbd == null) {//若根Bean定义为空,取这个BeanFactory所生产的实例
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {//若取不到,那么手动取
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;//把这个实例转化成一个FactoryBean
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {//若根Bean定义为空,但是容器内有Bean定义
                mbd = getMergedLocalBeanDefinition(beanName);//返回合并后的Bean定义
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());//标记这个Bean定义是合并的
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);//从工厂Bean中取
        }
        return object;
复制代码

  <5>、如果取不到、或 args 不为空(下面都是基于这个条件):

(如果对应的Bean正在被创建,就抛出异常)首先用父容器(如果本容器有的话)根据给出的形参取对应的Bean。

  <6>、此时,判断,如果不需要类型检查,标记其已经被创建。

  <7>、根据beanName取本地合并后的RootBeanDefinition(这个方法getMergedLocalBeanDefinition涉及到多层BeanDefinition相关的调用),然后检查一下。然后根据这个RootBeanDefinition,注册这个Bean和它的所有依赖。

  <8>、如果这个RootBeanDefinition是单例,先根据beanName从单例缓存中取,取不到就创建一个匿名内部Bean工厂,创建一个单例,直接结束方法。

  <9>、如果这个RootBeanDefinition是原型,就直接创建一个Bean返回,并在创建前把beanName与当前线程绑定,创建后解绑。

  <10>、如果这个RootBeanDefinition既不是单例,又不是原型,那么根据这个RootBeanDefinition定义的范围Scope,直接创建一个scopedInstance。

  <11>、若这个scopedInstance为工厂Bean,就得到它创建的实例,否则得到它自身。

  <12>、对<9>或<11>中最后产生的Bean就进行一次检查,要求这个产生的Bean的类型是否和Bean实例的类型匹配,不匹配就抛出异常。

  以上就是这个doGetBean方法了。其他的方法分析可参照上文的源码。

猜你喜欢

转载自www.cnblogs.com/JiangWJ/p/10800257.html