`
graykeel
  • 浏览: 15392 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

spring的bean的创建

阅读更多

spring作为一个轻量级J2EE应用框架,已经被广大的开发人员认为是最优秀的框架之一,得到了广泛的应用,其基于IOC的设计理念使得开发人员可以不必过多的关注框架层面的实现,可以更加专注于业务逻辑的实现。对于spring的分析文章已有很多,本人就将根据这就的理解来一步一步的分析spring的源代码,其中有不正确的地方还请大家拍砖指出,初次编写,有不好的地方请大家多多指正。
在spring的模块图如下:

spring一共包含7大模块,其中Spring Core模块是整个框架的最基础的部分,提供了IOC基础。Spring包的总体架构图如下:


从以上spring包的命名上看我们可以看出spring对j2ee提供了相当完善的支持,基本上是一个一站式服务的解决方案。
其中Core,beans包和context包是Spring Ioc的基础,没有他们也就没有了spring的上层应用如AOP,ORM,DAO等。在spring中,bean是最基本的元素,属于基础设施。而bean的创建获取操作均在beans包中完成。而bean是如何创建的呢?众所周知,BeanFactory是IoC容器的核心接口,它的职责包括:实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。进入BeanFactory中我们可以看到其提供的接口功能主要有:
//根据bean名字或者id获取bean实例对象
Object getBean(String name) throws BeansException;
//这里根据bean的名字或者id和Class类型来得到bean实例,
Object getBean(String name, Class requiredType) throws BeansException;
//根据bean的名称或者id和相应的参数获取bean的实例,此处对于作用域为singleton的会报错
Object getBean(String name, Object[] args) throws BeansException;
//检查容器中是否含有该名称或者id的bean
boolean containsBean(String name);
//根据bean的名称或者id判断该bean的作用域是否为singleton
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//根据bean的名称或者id判断该bean的作用域是否为prototype
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//根据所给的bean名称或者id和类类型来获取相应的bean实例
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
//根据所给的bean名称或者id获取该bean的类类型
Class getType(String name) throws NoSuchBeanDefinitionException;
//根据所给的bean的名称来获取或者id来获取该bean的别名
String[] getAliases(String name);


从上图中我们可以看到BeanFactory在当前包中有两个子类及一个实现类,即接口HierarchicalBeanFactory及ListableBeanFactory和实现类SimpleJndiBeanFactory,且在config包中有一个子类AutowireCapableBeanFactory,关于SimpleJndiBeanFactory(由spring2.5以后添加)我们暂且不关注其作用,先来看看剩下的三个接口:

接口名
作用
HierarchicalBeanFactory
此方法提供了两个接口,主要功能有判断当前BeanFactory中是否含有指定名称的bean、获取父BeanFactory
ListableBeanFactory
提供对容器内的bean的枚举与遍历功能:
查找是否有指定名称bean的定义
获取容器内bean的数量及所有bean的名称
根据指定类型获取bean的集合

AutowireCapableBeanFactory
提供自动装配的功能,即bean的创建等功能均由该接口实现,如createBean,autowireBean,configureBean等方法
从以上接口功能的设计及继承体系上看我们可以发现spring有着良好的接口设计,很好的体现了接口分级,不同级别的接口面对的对象不同,所需要提供的功能也不尽相同,和单一职责原则,并且接口分工明确,通过继承来完善和扩展主要接口的功能。其中BeanFactory属于spring的顶级接口,主要提供了与bean的查找的相关方法。其他继承自BeanFactory的接口,并从不同的方面完善了BeanFactory的功能。
就让我们先来看看bean是如何创建出来的?
对于接口AutowireCapableBeanFactory来说有一个子继承接口ConfigurableListableBeanFactory和一个抽象实现类AbstractAutowireCapableBeanFactory,相对于两个的子类来说,其最终的实现均为XmlBeanFactory。
AbstractAutowireCapableBeanFactory的依赖关系图


由上图我们可以看到AbstractAutowireCapableBeanFactory还继承了AbstractBeanFactory,并且在这个类中我们可以看到
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
我们进入CglibSubclassingInstantiationStrategy类中可以看到注释中有一段话“BeanFactory的默认类初始化策略”,其继承自SimpleInstantiationStrategy方法,我们可以在CglibSubclassingInstantiationStrategy类的注释中看到如果我们在应用中启用了CGLIB之后则spring将采用CGLIB来动态生成类的方式来实现方法的动态代理以及类的注入,当然BeanFactory容器仍然能够在CGLB没有使用的情况下正常工作。即如果在classpath写明了CGLIB运行库时将会采用CGLIB的动态代理,否则将采用JDK的默认动态代理。
由此可见如果在声明了CGLIB的情况下spring的bean创建默认是采用CGLIB的方式进行类的生成的。
AbstractAutowireCapableBeanFactory实现了AutowireCapableBeanFactory的接口的很多方法,在这里我们主要看spring的bean的创建过程,所以就先看看关于createBean的方法:
//根据给出的类来创建bean的实例,该方法创建的是一个全新的bean实例
Object createBean(Class beanClass) throws BeansException;
//根据指定装载策略和类创建一个该类的实例,装载策略包括AUTOWIRE_NO,AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE,AUTOWIRE_CONSTRUCTOR,AUTOWIRE_AUTODETECT
Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
关于两个方法的实现如下:
public Object createBean(Class beanClass) throws BeansException {
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}

public Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}
两个实现类的唯一区别在于RootBeanDefinition bd = new RootBeanDefinition(beanClass);和RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);上面。其中RootBeanDefinition继承自AbstractBeanDefiniton,而从下图我们可以看出:

RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition均继承了AbstractBeanDefiniton,其中BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。<bean>元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的beanClass、scope、lazyInit属性,BeanDefinition和<bean>中的属性是一一对应的。其中RootBeanDefinition是最常用的实现类,它对应一般性的<bean>元素标签,GenericBeanDefinition是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类。在配置文件中可以定义父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而没有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。
Spring通过BeanDefinition将配置文件中的<bean>配置信息转换为容器的内部表示,并将这些BeanDefiniton注册到BeanDefinitonRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,主要是以map的形式保存,后续操作直接从BeanDefinitionRegistry中读取配置信息。一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化,当然如果用户有特殊的需求,也可以通过编程的方式在运行期调整BeanDefinition的定义。
创建最终的BeanDefinition主要包括两个步骤:
1)利用BeanDefinitionReader对配置信息Resource进行读取,通过XML解析器解析配置信息的DOM对象,简单地为每个<bean>生成对应的BeanDefinition对象。但是这里生成的BeanDefinition可能是半成品,因为在配置文件中,我们可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步还没有被解析出来。
2)利用容器中注册的BeanFactoryPostProcessor对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就为成品的BeanDefinition。

ConfigurableListableBeanFactory介绍


该接口的主要提供了一些分析和更改BeanDefinition的方法以及单例bean的预创建功能。从该类的继承关系上看我们发觉该接口同时继承了ListableBeanFactory, AutowireCapableBeanFactory以及ConfigurableBeanFactory接口,而HierarchicalBeanFactory则继承了HierarchicalBeanFactory和 SingletonBeanRegistry接口,由此可见一个ConfigurableListableBeanFactory就拥有了所有的这些接口功能,而其为什么还要分出这么多的接口类出来呢!?这就是接口的分级设计及单一功能体现,不同的接口提供不同的功能,并通过接口的继承来完善和扩展功能。
该接口具有一个实现类DefaultListableBeanFactory,该类通过一系列的继承实现了这些接口的所有方法,至此有关spring bean的创建,定义以及bean间关系的建立等均已完成,但是对于资源的读取并没有实现,通过下图我们可以看出

DefaultListableBeanFactory还有一个子类XmlBeanFactory,XmlBeanFactory是BeanFactory的一个常用实现,
进入该子类可以看出里面仅有两个构造方法:
//根据给出的资源创建XmlBeanFactory
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//根据给出的资源以及父 BeanFactory创建XmlBeanFactory
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
现在我们可以总结出整个bean的生成过程了:
1:生成xml格式的配置文件
2:通过ResourceLoader将配置文件读入
3:通过BeanDefinitionReader将配置信息转换程BeanDefinition
4:在通过BeanFactory根据BeanDefinition信息创建bean实例
5:将bean实例放入SingletonBeanRegistry中以供使用
现在我们来看看bean的产生过程中这些接口,类的功能的划分,继承的层级可以发现spring对每一个功能都进行了很好的抽象,并进行了良好的接口功能划分,如BeanFactory接口,及其子类接口,虽然在最终我们看到只有一个类即DefaultListableBeanFactory通过继承实现了这些所有的接口。但是从这一点上我们可以看出spring将类的功能划分的非常细致,并不是讲所有的功能通过一个接口来体现,而是一步一步的分层级来实现这些功能,尽可能高度的抽象。

 

  • 大小: 103.9 KB
  • 大小: 12.3 KB
  • 大小: 261.7 KB
  • 大小: 105.9 KB
  • 大小: 78.2 KB
  • 大小: 62.5 KB
  • 大小: 4.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics