九、Spring之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 接口相关的主要的继承结构:
上面的继承关系去除了目前不需要的类。
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类图
对于左边部分,则是各种功能的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一个继承结构吧(非完整继承结构)
一个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 ,就容器方面而言功能已经健全了。
推荐阅读
-
九、Spring之BeanFactory源码分析(一)
-
Spring源码分析之IoC容器初始化
-
Mybaits 源码解析 (九)----- 全网最详细,没有之一:一级缓存和二级缓存源码分析
-
Dubbo源码分析之 SPI(一)
-
spring-boot-2.0.3不一样系列之源码篇 - SpringApplication的run方法(一)之SpringApplicationRunListener,绝对有值得你看的地方
-
Springboot源码分析之Spring循环依赖揭秘
-
Spring源码分析(一)
-
Spring源码分析(一)
-
Spring源码分析之与WEB服务器衔接(下)
-
Spring源码分析之与WEB服务器衔接(上)