欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

九、Spring之BeanFactory源码分析(一)

程序员文章站 2023-10-29 12:56:16
Spring之BeanFactory源码分析(一) ​ 注意:该随笔内容完全引自,写的很好,非常感谢,复制过来算是个积累,怕以后找不到。 BeanFactory BeanFactory提供的是最基本的IOC容器的功能,BeanFactory 只是一个接口类,并没有给出容器的具体实现,当然,它有不同的 ......

spring之beanfactory源码分析(一)

​ 注意:该随笔内容完全引自,写的很好,非常感谢,复制过来算是个积累,怕以后找不到。

beanfactory

beanfactory提供的是最基本的ioc容器的功能,beanfactory 只是一个接口类,并没有给出容器的具体实现,当然,它有不同的实现类,来定义或者扩充某个功能。这篇文章的主角就是它啦。

启动ioc容器

下面是一段简单的代码,通过编程启动ioc 容器:

public void testdefaultlistablebeanfactory(){

  classpathresource resource  = new classpathresource("spring.xml");

  defaultlistablebeanfactory factory = new defaultlistablebeanfactory();

  xmlbeandefinitionreader reader = new xmlbeandefinitionreader(factory);

  reader.loadbeandefinitions(resource);

  mybean bean = factory.getbean(mybean.class);

  system.out.println(bean.tostring());
}

spring.xml 配置文件里面很简单:

<bean id="mybean" class="com.study.spring.bean.mybean" />

这样,我们就可以通过factory对象来使用defaultlistablebeanfactory 这个ioc容器了,在使用ioc容器时,需要如下步骤:
1)创建ioc配置文件的抽象资源,即配置文件

2)创建一个beanfactory,这里使用defaultlistablebeanfactory

3)创建一个载入beandefinition的读取器,这里使用xmlbeandefinitionreader 来载入xml文件形式的beandefinition。

4)从定义好的资源位置读取配置信息,具体的解析过程由xmlbeandefinitionreader 来完成。

通过一个简短的代码就可以启动spring,核心就在于defaultlistablebeanfactory,暂时就不直接跟踪流程了,还是来看看整个beanfactory的设计。

beanfactory 类结构体系

beanfactory,从名字上也很好理解,生产管理 bean 的工厂(容器),它负责生产和管理各个 bean 实例。

我们来看下和 beanfactory 接口相关的主要的继承结构:

九、Spring之BeanFactory源码分析(一)

上面的继承关系去除了目前不需要的类。

emmmmm,这图看着有点头大,慢慢来,先主要关注左边部分,梳理一下各个beanfactory的职能,怎么梳理?,看源码咯。

beanfactory

beanfactory 是*接口,定义了ioc容器最基本的形式。

public interface beanfactory {

    //这里可以暂时不用管
    string factory_bean_prefix = "&";

    object getbean(string name) throws beansexception;
    ... //省略其它方法
}

定义了一些基本接口,例如 获取bean,当然还有一些其它接口,这里就不列出了,需要自己去了解一下。

至于 factory_bean_prefix 这个其实在这里可以忽略,这里还是简单提一下,如果不明白也无妨,与beanfactory很相似的有一个叫factorybean的类,从名字上很容易混淆,beanfactory 首先是factoyr,而factorybean 是bean,只是 是一种特殊的bean, 这种特殊的bean会生产另一种bean, 对于普通的bean,通过beanfactory 的 getbean方法可以获取这个bean,而对于factorybean 来说,通过getbean 获得的是 factorybean 生产的bean,而不是factorybean 本身,如果想要获取factorybean 本身,那么可以加前缀&,那么spring 就明白,原来你是需要factorybean 。这个可能会在后面aop的部分,展开来讲,这里就先说这么多了。

listablebeanfactory

public interface listablebeanfactory extends beanfactory {

    // 对于给定的名字是否含有beandefinition
    boolean containsbeandefinition(string beanname);

    // 返回工厂的beandefinition总数
    int getbeandefinitioncount();
    
    // 返回工厂中所有bean的名字
    string[] getbeandefinitionnames();

    // 返回对于指定类型 获取bean的名字
    string[] getbeannamesfortype(resolvabletype type);
    
    //获取包含某个注解 bean的名字
    string[] getbeannamesforannotation(class<? extends annotation> annotationtype);

    // 根据指定bean名和注解类型查找指定的bean
    <a extends annotation> a findannotationonbean(string beanname, class<a> annotationtype)
            throws nosuchbeandefinitionexception;
}

hierarchicalbeanfactory

public interface hierarchicalbeanfactory extends beanfactory {

    beanfactory getparentbeanfactory();

    /**
     * return whether the local bean factory contains a bean of the given name,
     * ignoring beans defined in ancestor contexts.
     * <p>this is an alternative to {@code containsbean}, ignoring a bean
     * of the given name from an ancestor bean factory.
     */
    boolean containslocalbean(string name);

}

分层式的beanfactory,这个工厂接口非常简单,实现了bean工厂的分层。相对于beanfactory接口,它只扩展了一个重要的功能——工厂分层,可以指定父工厂(容器),同时查找bean的时候,可以只查找本容器,忽略父容器。

autowirecapablebeanfactory

public interface autowirecapablebeanfactory extends beanfactory {

    //  这个常量表明工厂没有自动装配的bean
    int autowire_no = 0;

    //表明根据名称自动装配
    int autowire_by_name = 1;

    //表明根据类型自动装配
    int autowire_by_type = 2;

    //表明根据构造方法装配
    int autowire_constructor = 3;

    //被废弃了
    @deprecated
    int autowire_autodetect = 4;

    <t> t createbean(class<t> beanclass) throws beansexception;

    //  给定对象,根据注释、后处理器等,进行自动装配
    void autowirebean(object existingbean) throws beansexception;

    ...//省略后续方法
}

autowirecapablebeanfactory 目前还没有深入的研究,这个beanfactory 增加了注解功能,可以通过注解进行装配(操作)的工厂(容器)。

小结

上面三个 factory 是 beanfactory 接口的直系亲属,三种不同样式的beanfactory ,分层容器,可列举(查询)容器,自动装配容器,职能单一原则,这种接口设计,应该平常工作中经常遇到吧。

接下来在看看其它更多样化的 beanfactory 。

configurablebeanfactory

public interface configurablebeanfactory extends hierarchicalbeanfactory, singletonbeanregistry {

    string scope_singleton = "singleton";

    string scope_prototype = "prototype";
    
    //设置父容器
    void setparentbeanfactory(beanfactory parentbeanfactory) throws illegalstateexception;

    void setbeanclassloader(classloader beanclassloader);

    classloader getbeanclassloader();

    void setbeanexpressionresolver(@nullable beanexpressionresolver resolver);

    beanexpressionresolver getbeanexpressionresolver();

    /*
     * 设置 转换服务
     */
    void setconversionservice(conversionservice conversionservice);

    conversionservice getconversionservice();

    void addpropertyeditorregistrar(propertyeditorregistrar registrar);

    /*
     * 注册属性编辑器
     */
    void registercustomeditor(class<?> requiredtype, class<? extends propertyeditor> propertyeditorclass);

    void copyregisterededitorsto(propertyeditorregistry registry);

    void settypeconverter(typeconverter typeconverter);

    typeconverter gettypeconverter();

    //设置一个bean后处理器
    void addbeanpostprocessor(beanpostprocessor beanpostprocessor);

    int getbeanpostprocessorcount();

    void registerscope(string scopename, scope scope);

    string[] getregisteredscopenames();

    scope getregisteredscope(string scopename);

    void copyconfigurationfrom(configurablebeanfactory otherfactory);
    /*
     * 给指定的bean注册别名
     */
    void registeralias(string beanname, string alias) throws beandefinitionstoreexception;

    beandefinition getmergedbeandefinition(string beanname) throws nosuchbeandefinitionexception;

    //判断指定bean是否为一个工厂bean
    boolean isfactorybean(string name) throws nosuchbeandefinitionexception;

    void setcurrentlyincreation(string beanname, boolean increation);

    boolean iscurrentlyincreation(string beanname);

    void registerdependentbean(string beanname, string dependentbeanname);

    string[] getdependentbeans(string beanname);

    string[] getdependenciesforbean(string beanname);

    void destroybean(string beanname, object beaninstance);

    void destroyscopedbean(string beanname);

    void destroysingletons();
    
    ...//省略部分方法

}

configurablebeanfactory 继承了 hierarchicalbeanfactory,singletonbeanregistry

先看一下接口singletonbeanregistry的源码:

singletonbeanregistry

public interface singletonbeanregistry {

    //注册一个单例类  
    void registersingleton(string beanname, object singletonobject);


    object getsingleton(string beanname);


    boolean containssingleton(string beanname);


    string[] getsingletonnames();

    int getsingletoncount();

    //不清楚
    object getsingletonmutex();

}

可以看到,singletonbeanregistry这个接口非常简单,实现了单例类注册的功能。

configurablebeanfactory同时继承了hierarchicalbeanfactory 和 singletonbeanregistry 这两个接口,即同时继承了分层和单例类注册的功能。

configurablebeanfactory 正如其名字一样,可以配置的beanfactory,里面有很多接口方法,我也没有去细研究每一个方法,后面用到了,再来具体分析就可以了,了解了解,知道大概用处就可以了。

configurablelistablebeanfactory

public interface configurablelistablebeanfactory
        extends listablebeanfactory, autowirecapablebeanfactory, configurablebeanfactory {

    //忽略自动装配的依赖类型
    void ignoredependencytype(class<?> type);
    
    //忽略自动装配的接口
    void ignoredependencyinterface(class<?> ifc);

    //返回注册的bean定义
    beandefinition getbeandefinition(string beanname) throws nosuchbeandefinitionexception;


    iterator<string> getbeannamesiterator();

    ...//忽略部分方法
}

工厂接口configurablelistablebeanfactory同时继承了3个接口,listablebeanfactory、autowirecapablebeanfactory 和 configurablebeanfactory,可以说功能以及很全面了。

对于beanfactory 体系中左边部分,大致差不多了,现在看看右半边情况

beandefinitionregistry

顾名思义,这个是注册 beandefinition的

public interface beandefinitionregistry extends aliasregistry {

    //给定bean名称,注册一个新的bean定义
    void registerbeandefinition(string beanname, beandefinition beandefinition)
            throws beandefinitionstoreexception;

    //根据指定bean名移除对应的bean定义
    void removebeandefinition(string beanname) throws nosuchbeandefinitionexception;

    根据指定bean名得到对应的bean定义
    beandefinition getbeandefinition(string beanname) throws nosuchbeandefinitionexception;

    查找,指定的bean名是否包含bean定义
    boolean containsbeandefinition(string beanname);

    //返回本容器内所有注册的bean定义名称
    string[] getbeandefinitionnames();

    //指定bean名是否被注册过。
    int getbeandefinitioncount();

   //指定bean名是否被注册过。
    boolean isbeannameinuse(string beanname);

}

这个接口很简单,就是对beandefinition的操作,然而我们还没有了解beandefinition 的结构,但是并不影响我们分析,因为从名字就知道这个指代的是一个bean的定义,也就是将xml中的bean 翻译成了具体的数据结构。

现在回过头来,我们再看看defaultlistablebeanfactory类图

九、Spring之BeanFactory源码分析(一)

对于左边部分,则是各种功能的beanfactory,右边部分则是对beandefinition的功能操作,中间部分则是单例bean功能服务,中间部分我们没有分析源代码,但是通过名字我们已经很好的知道了它的功能,而factorybeanregistrysupport 则表示了对 factorybean的支持,(factorybean在前面beanfactory简单提了一下哟)

现在对每个beanfactory的职能心里大概有谱了,这样在后面的时候,才知道这个功能属于哪个模块,而不至于脑袋一团浆糊。

对于defaultlistablebeanfactory 我们并没有取分析它,因为defaultlistablebeanfactory 中实现了上面接口中的所有方法,涉及了很多细节,从代码角度来看的话,那真的是很难一下分析透,但是如果从功能模块上来看的话,我们也知道了它大概可以干什么,可以说是一个比较成熟的容器了,既然现在我们知道了装bean的容器了,那么bean又从何处来呢,当然是xml,但是xml又如何转换成数据结构的呢,这个就需要回到我们最开的代码了:

public void testdefaultlistablebeanfactory(){

  classpathresource resource  = new classpathresource("spring.xml"); //3

  defaultlistablebeanfactory factory = new defaultlistablebeanfactory(); //5

  xmlbeandefinitionreader reader = new xmlbeandefinitionreader(factory);//7

  reader.loadbeandefinitions(resour ce);//9

  mybean bean = factory.getbean(mybean.class); //11

  system.out.println(bean.tostring());

}

现在第5,11行代码我们已经大致清楚了,主要的还剩3,4,9行代码了,这个就先留到后面再来吧。

beandefinition

bean的定义主要由beandefinition来描述的,作为spring中用于包装bean的数据结构,先来看看beandefinition一个继承结构吧(非完整继承结构)

九、Spring之BeanFactory源码分析(一)

一个beandefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。

beandefinition 源码浅析

//标准单例作用域 标识符:“singleton”。
string scope_singleton = configurablebeanfactory.scope_singleton;

//标准原型作用域的范围标识符:“prototype”。
string scope_prototype = configurablebeanfactory.scope_prototype;

//表示beandefinition是应用程序主要部分的角色提示。 通常对应于用户定义的bean。
int role_application = 0;

//表示beandefinition是某些大型配置的支持部分的角色提示,通常是一个外部componentdefinition。
//当查看某个特定的componentdefinition时,认为bean非常重要,
//以便在查看应用程序的整体配置时能够意识到这一点。

int role_support = 1;

//角色提示表明一个beandefinition是提供一个完全背景的角色,并且与最终用户没有关系。

role_support =1实际上就是说,我这个bean是用户的,是从配置文件中过来的。

role_infrastructure = 2 就是说 这bean是spring自己的,

上面是beandifinition的一些基本属性信息,一个就是标识下当前bean的作用域,另外就是标识一下这个bean是内部的还是外部的。下面来看这个接口为其子类都提供了哪些具体的行为方法:
1.当前bean的classname get&set方法

//指定此bean定义的bean类名称。
//类名称可以在bean factory后期处理中修改,通常用它的解析变体替换原来的类名称。
void setbeanclassname(string beanclassname);

//返回此bean定义的当前bean类名称。
//需要注意的是,这不一定是在运行时使用的实际类名,以防子类定义覆盖/继承其父类的类名。
//此外,这可能只是调用工厂方法的类,或者它 在调用方法的工厂bean引用的情况下甚至可能是空的。
//因此,不要认为这是在运行时定义的bean类型,而只是将其用于在单独的bean定义级别进行解析。
string getbeanclassname();

2.bean的作用域get&set方法

//覆盖此bean的目标范围,指定一个新的范围名称。
void setscope(string scope);
//返回此bean的当前目标作用域的名称,如果没有确定,返回null
string getscope();

3.懒加载的get&set方法

//设置这个bean是否应该被延迟初始化。如果{false},那么这个bean将在启动时由bean工厂实例化,
//这些工厂执行单例的立即初始化。
//懒加载 <bean lazy-init="true/false">
void setlazyinit(boolean lazyinit);
//返回这个bean是否应该被延迟初始化,即不是在启动时立即实例化。只适用于单例bean。
boolean islazyinit();

4.依赖关系设置

//设置这个bean依赖被初始化的bean的名字。 bean工厂将保证这些bean首先被初始化。
//<bean depends-on="">
void setdependson(string... dependson);
//返回这个bean依赖的bean名称。
string[] getdependson();

5.是否是自动转配设置

//设置这个bean是否是获得自动装配到其他bean的候选人。
//需要注意是,此标志旨在仅影响基于类型的自动装配。
//它不会影响按名称的显式引用,即使指定的bean没有标记为autowire候选,也可以解决这个问题。
//因此,如果名称匹配,通过名称的自动装配将注入一个bean。
void setautowirecandidate(boolean autowirecandidate);

//返回这个bean是否是自动装配到其他bean的候选者。就是是否在其他类中使用autowired来注入当前bean的
//是否为被自动装配 <bean autowire-candidate="true/false">
boolean isautowirecandidate();

并没有完全列举 beandifinition 中的方法或者属性,大致明白 bean的定义主要由beandefinition来描述的,作为spring中用于包装bean的数据结构就可以了,关于beandifinition 的更多接口实现,这个根据自己情况去看看就可以了。

小结

了解了beanfactory的大致结构后,来看看下面一段简单代码,相信理解就更加深刻了:

public void testdefaultlistablebeanfactory(){

  defaultlistablebeanfactory factory = new defaultlistablebeanfactory();

  abstractbeandefinition beandefinition = new rootbeandefinition(mybean.class);

  factory.registerbeandefinition("mybean",beandefinition);

  //可以通过构造方法注入依赖,当然我们这里没有
  //beandefinition.setconstructorargumentvalues();

  //可以通过 setter 方法注入依赖,当然我们这里也没有
  //beandefinition.setpropertyvalues();

  mybean bean = factory.getbean(mybean.class);

  system.out.println(bean.tostring());

}

在前面我们用的classpathresource,xmlbeandefinitionreader 从文件中读取的bean配置信息,现在我们知道了beandifinition 以及beandefinitionregistry,那么其实我们可以手动注册beandifinition ,这样我在最开始的代码基础上,又再次细分了功能了,层次也更加的清楚了。

总结

我们从 defaultlistablebeanfactory 出发,大致了解了一下 beanfactory的体系结构,beanfactory有三个直系亲属:

listablebeanfactory(可列举的容器(多花样查询)),hierarchicalbeanfactory(分层次容器,可有父容器),autowirecapablebeanfactory(自动装配容器),这三个容器定义了beanfactory的基本面貌,在这个三个直系亲属下面又派生了两个复杂的容器:configurablebeanfactory,configurablelistablebeanfactory,可配置的(可操作)的容器,通过这两个beanfactory 可有修改容器中的bean,功能又更加高级了,集成了单例bean 服务,以及beandefinition 注册服务,那么对于 defaultlistablebeanfactory 来说,此时它就是一个可注册,可配置,可获取的beanfactory ,就容器方面而言功能已经健全了。