关键词不能为空

当前您在: 主页 > 英语 >

spring内核详解

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-02-06 02:02
tags:

-

2021年2月6日发(作者:yeg)


Spring


作为现在最优秀的框架之一,已被广泛的使用,

< p>
51CTO


也曾经针对


Spring


框架中的


JDBC


应用


做过 报


道。本文将从另外一个视角试图剖析出


Spring


框架的作者设计


Spring


框架的骨骼架构的 设计理念,有那几个核


心组件?为什么需要这些组件?它们又是如何结合在一起构成


Spring


的骨骼架构?


Spring< /p>



AOP


特性又是如何

< br>利用这些基础的骨骼架构来工作的?


Spring


中又使 用了那些设计模式来完成它的这种设计的?它的这种



设计理< /p>


念对对我们以后的软件设计有何启示?本文将详细解答这些问题。



Spring


的骨骼架构


< p>
Spring


总共有十几个组件,但是真正核心的组件只有几个,下面是< /p>


Spring


框架的总体架构图:






框架的总 体架构图



从上图中可以看出


Spri ng


框架中的核心组件只有三个:


Core


Context



Beans< /p>



它们构建起了整个


Spring


的骨骼架构。没有它们就不可能有


AOP


、< /p>


Web


等上层的特性功能。下面也将主要从这三个组件入手分析< /p>


Spring




Spring


的设计理念


< p>
前面介绍了


Spring


的三个核心组件,如果再 在它们三个中选出核心的话,那就非


Beans


组件莫属了,为 何


这样说,其实


Spring


就是面向


Bean


的编程(


BOP,Bean Oriented Programming


),


Bean



Spring


中才是真正


的主角。



Bean



Spring


中作 用就像


Object



OOP


的意义一样,没有对象的概念就像没有面向对象编程,


Spring



没有


Bean


也 就没有


Spring


存在的意义。就像一次演出舞台都准备好了 但是却没有演员一样。为什



么要


Be an



种角色


Bean


或者为何在


Spring


如此重要,

< br>这由


Spring


框架的设计目标决定,


Spring


为何如此流行,


我们用

< br>Spring


的原因是什么,


想想你会发现原来


Spring


解决了一个非常关键的问题他可以让



你把对象之间的依赖关系转而用


配置文件来管理,也就是他 的依赖注入机制。而这个注入关系在一个叫


Ioc


容器中管理, 那


Ioc


容器中有又是什


么就是被


Bean


包裹的对象。


Spring


正是通过把对象包装在


Bean


中而达到对 这些对象管理以及一些列额外操作


的目的。


< br>它这种设计策略完全类似于


Java


实现


OOP


的设计理念,


当然了


J ava


本身的设计要比


Spring


复 杂太多太多,


但是都是构建一个数据结构,然后根据这个数据结构设计他的生存环境,并 让它在这个环境中



按照一定的规律


在 不停的运动,在它们的不停运动中设计一系列与环境或者与其他个体完成信息交换。这样想来回过头想想我们


用到的其他框架都是大慨类似的设计理念。



核心组件如何协同工作



前面说


Bean



Spring

中关键因素,



Context



Core


又有何作用呢?前面吧


Bea n


比作一场演出中的演员


的话,那


Co ntext


就是这场演出的舞台背景,而


Core


应该就是演出的道具了。只有他们在一起才能



具备 能演出


一场好戏的最基本的条件。当然有最基本的条件还不能使这场演出脱颖而出,还要 他表演的节目足够的精彩,这


些节目就是


Spring


能提供的特色功能了。



我们知道


Bean


包装的是


Object



Object


必然有数据,< /p>


如何给这些数据提供生存环境就是


Context


要解决


的问题,对


Context

来说他就是要发现每个


Bean


之间的关系,为它们建立这 种关系并且要维护好



这种关系。所



Context


就是一个


Bean


关系的集合,这个关系集合又叫


Ioc


容器 ,一旦建立起这个


Ioc


容器后


Spr ing


就可以


为你工作了。那


Core


组件又有什么用武之地呢?其实


Core


就是发现、建立和维护每




Bea n


之间的关系所需要


的一些列的工具,从这个角度看来,


Core


这个组件叫


Util


更能让你理解。



它们之间可以用下图来表示:





2.


三个组件关系



核心组件详解



这里将详细介绍每 个组件内部类的层次关系,以及它们在运行时的时序顺序。我们在使用


Spring


是应该注


意的地方。



Bean


组件



前面已经说明了


Bean


组件对


Sp ring


的重要性,下面看看


Bean


这个组件式怎么设计的。


Bean


组件在


Spring




包下。这个包下的所 有类主要解决了三件事:


Bean


的定义、

Bean


的创建以及对


Bean


的解析。



Spring


的使用者来说 唯一需要关心的就是


Bean


的创建,


其他两个由


Spring


在内部帮你完成了,

< br>对你来说是透明的。



SpringBean

< p>
的创建时典型的工厂模式,他的顶级接口是


BeanFactory


,下图是这个工厂的继承层次关系:



< /p>




工厂的继承关系



BeanFactory


有三个子类:

ListableBeanFactory



Hierar chicalBeanFactory



Autowire Capable Bean


Factory



但是从上图中我们可以发现最终的默认实现类是


DefaultListabl eBeanFactory



他实


< /p>


现了所有的接口。


那为何要定义这么多层次的接口呢?查阅这些接 口的源码和说明发现,每个接口都有他使用的场合,它主要是为


了区分在


Spring


内部在操作过程中对象的传递和转化过程中,对对象的

< p>


数据访问所做的限制。例如


ListableB eanFactory


接口表示这些


Bean

< br>是可列表的,而


HierarchicalBeanFactory


表示的是这些


Bean


是有继


承关系的,也就是每个


Bean


有可能有父

< br>Bean



AutowireCapableBean Factory


接口定义


Bean


的自 动装配规则。


这四个接口共同定义了


Bean

< br>的集合、


Bean


之间的关系、以及

Bean


行为。



Bean


的定义主要有


BeanDefinition


描述,如下图说明了这些类的层次关系:



< br>图



定义的类层次关系图



Bean


的定义就是完整的描述了在


Spri ng


的配置文件中你定义的节点中所有的信息,包括各种子节点。当

Spring


成功解析你定义的一个节点后,在


Sprin g


的内部他就被转化




BeanDefinition


对象。以后所有的操作


都是对这个对象完成的。



Bean


的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,

< p>
以应对可能的变化。


Bean


的解析主要就是对< /p>


Spring


配置文件的解析。这个解析过程主要通过

< p>


下图中的类完成:






的解析类



当然还有具体对


tag


的解析这里并没 有列出。



Context


组件



Context



Spring



t


包下,前面已经讲解了


Cont ext


组件在


Spring


中的作


用,他实际上就是给


Spring


提供一个 运行时的环境,用以保存各个对象的状态。下面看一下这个



环境是如何构


建的。



ApplicationContext



Conte xt


的顶级父类,


他除了能标识一个应用环境的基本信息外,< /p>


他还继承了五个接


口,这五个接口主要是扩展了

< br>Context


的功能。下面是


Context


的类结构图:




图< /p>


t


相关的类结构图


从上图中可以看出


ApplicationContext


继承了


BeanFactory


,这也说明了

< br>Spring


容器中运行的主体对象是


Bean


,另外


ApplicationContext


继承了


ResourceLoader


接口,使得


ApplicationContext


可以访


< /p>


问到任何外部


资源,这将在


Core


中详细说明。



ApplicationC ontext


的子类主要包含两个方面:


ConfigurableApplicationContext


表示该


Context


是可修改的,


也就是在构建


Context


中用户可以动态添加


或修改 已有的配置信息,它下面又有多个子类,其中最经常使用的是可更新的


Context< /p>


,即



AbstractRefresh ableApplicationContext


类。



WebApplicationContext


顾名思义,就是为


web


准备的


Context


他可以直接访问到


ServletContext


, 通常情


况下,这个接口使用的少。



再 往下分就是按照构建


Context


的文件类型,接着就是访问


Context


的方式。这样一级一级构成了完整的

< p>
Context


等级层次。


总体来说


ApplicationContext


必须要完 成以下几件事:



◆标识一个应用环境



◆利用


BeanFactory


创建< /p>


Bean


对象



◆保存对象关系表



◆能够捕获各种事件



Context


作为


Spring


< br>Ioc


容器,基本上整合了


Spring


的大部分功能,或者说是大部分功能的基础。



Core


组件



Core


组件作为


Spring


的核 心组件,他其中包含了很多的关键类,其中一个重要组成部分就是定义了资源的


访问方式 。这种把所有资源都抽象成一个接口的方式很值得在以后的设计中拿来学习。下面就


< /p>


重要看一下这个


部分在


Spring


的作用。



下图是


Resource


相关的类结构图:





ce


相关的类结构图



从上图可以看出


Resource

< br>接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同。


对 资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,我们看到


Res ource


接口继承了


InputStreamSource


接口,


这个接口中有个


getInpu tStream


方法,


返回的是


Inp utStream


类。


这样所有的资源都


被可以通过


InputStream


这个类来获取,


所以也屏蔽了资源的提供者。


另外还有一



个问题就是加载资源的问题,


也就是资源的加载者要统一,从上图中 可以看出这个任务是由


ResourceLoader


接口完成 ,他屏蔽了所有的资源


加载者的差异,只需要实现这个接口就可以加载所有的资源,



他的默认实现是


DefaultReso urceLoader




下面看一下


Context



Resource< /p>


是如何建立关系的?首先看一下他们的类关系图:





t



Resource


的类关系图


< p>
从上图可以看出,


Context


是把资源的加载 、


解析和描述工作委托给了


ResourcePatternR esolver


类来完成,


他相当于一个接头人,他把资源的加 载、解析和资源的定义整合在一起便于其他组件使用。


Core


组件中还有很


多类似的方式。



Ioc


容器如何工作



前面介绍了


Core


组件、


B ean


组件和


Context


组件的结 构与相互关系,下面这里从使用者角度看一下他们是


如何运行的,以及我们如何让


Spring


完成各种功能,


Spring< /p>


到底能有那些功能,这些功能是如



何得来的,下面


介绍。



如何创建


BeanFactory


工厂



正如图


2


描述的那样,< /p>


Ioc


容器实际上就是


Context< /p>


组件结合其他两个组件共同构建了一个


Bean

< br>关系网,



何构建这个关系网?构建的入口就在


AbstractApplicationContext


类的


refresh


方法中。


这个方



法的代码如下:



清单


h



1.



public void refresh() throws BeansException, IllegalStateException {



2.





3.



synchronized (pShutdownMonitor) {



4.





5.



// Prepare this context for refreshing.



6.





7.



prepareRefresh();



8.





9.



// Tell the subclass to refresh the internal bean factory.



10.





11.



ConfigurableListableBeanFactory


beanFactory


=


obtainFreshBeanFactory


();



12.





13.



// Prepare the bean factory for use in this context.



14.





15.



prepareBeanFactory(beanFactory);



16.





17.



try {



18.





19.



// Allows post- processing of the bean factory in context subclasses.



20.





21.



postProcessBeanFactory(beanFactory);



22.





23.



// Invoke factory processors registered as beans in& nbsp;the context.



24.





25.



invokeBeanFactoryPostProcessors(beanFactory);



26.





27.



// Register bean processors that intercept bean crea tion.



28.





29.



registerBeanPostProcessors (beanFactory);



30.





31.



// Initialize message source for this context.



32.





33.



initMessageSource();



34.





35.



// Initialize event multicaster for this context.



36.





37.



initApplicationEventMulticaster();



38.





39.



// Initialize other special beans in specific contex t subclasses.



40.





41.



onRefresh();



42.





43.



// Check for listener beans and register them.



44.





45.



registerListeners();



46.





47.



// Instantiate all remaining (non-lazy-init) singletons.



48.





49.



finishBeanFactoryInitialization (beanFactory);



50.





51.



// Last step: publish corresponding event.



52.





53.



finishRefresh();



54.





55.



}



56.





57.



catch (BeansException ex) {



58.





59.



// Destroy already created singletons to avoid dangl ing resources.



60.





61.



destroyBeans();



62.





63.



// Reset 'active' flag.



64.





65.



cancelRefresh(ex);



66.





67.



// Propagate exception to caller.



68.





69.



throw ex;



70.





71.



}



72.





73.



}



74.





75.



}



76.





这个方法就是构建整个


Ioc


容器过程的完整的代码,了解了里面的每一行代码基本上就了解大部分


Spring


的原理和功能了。



这段代码主要包含这样几个步骤:



◆ 构建


BeanFactory


,以便于产生所需的“演员”



◆注册可能感兴趣的事件



◆创建


Bean


实例对象



◆触发被监听的事件



下面就结合代码分析这几个过程。



第 二三句就是在创建和配置


BeanFactory


。这里是


refresh


也就是刷新配置,前面介绍了


Context


有可更新


的子类,


这 里正是实现这个功能,



BeanFactory


已存在是就更新,


如果没有就新创建。


下面是



更新


BeanFactory


的方法代码:



清单


2. AbstractRefreshableApplicationContext. refreshBeanFactory



1.



protected final void refreshBeanFactory() throws BeansException {



2.





3.



if (hasBeanFactory()) {



4.





5.



destroyBeans();



6.





7.



closeBeanFactory();



8.





9.



}



10.





11.



try {



12.





13.



DefaultListableBeanFactory


beanFactory


=


createBeanFactory


();



14.





15.



ializationId(getId());



16.





17.



customizeBeanFactory(beanFactory);



18.





19.



loadBeanDefinitions(beanFactory);



20.





21.



synchronized (ctoryMonitor) {



22.





23.




ctory


= beanFactory;



24.





25.



}



26.





27.



}



28.





29.



catch (IOException ex) {



30.





31.



throw new ApplicationContextException(



32.





33.





34.





35.



+ getDisplayName (), ex);



36.





37.



}



38.





39.



}



40.





这个方法实现了


AbstractA pplicationContext


的抽象方法


refres hBeanFactory


,这段代码清楚的说明了


BeanF actory


的创建过程。


注意


Bea nFactory


对象的类型的变化,




面介绍了他有很多子类,


在什么情况下使用


不同的子类这非常关键。


BeanFactory


的原 始对象是


DefaultListableBeanFactory

,这个非常关键,因为他设计


到后面对这个对象的多种操作,下面看一下这个



类的继承层次类图:





tListableBeanFa ctory


类继承关系图



从这个图中 发现除了


BeanFactory


相关的类外,


还发现了与


Bean



reg ister


相关。


这在


refresh BeanFactory


方法中有一行


loadBeanDef initions(beanFactory)


将找到答案,这个方法将开始加载、解析


Bean


的定义,也就


是把用户定义 的数据结构转化为


Ioc


容器中的特定数据结构。



这个过程可以用下面时序图解释:





11.


创 建


BeanFactory


时序图


< /p>


Bean


的解析和登记流程时序图如下:





12.


解 析和登记


Bean


对象时序图



创建好


BeanFactory


后,接下去添 加一些


Spring


本身需要的一些工具类,这个操作在


AbstractApplicationContext



prepareBeanFactory


方法完成。


AbstractApplicationContext


中接下来的三行代码对


Spring


的功能扩展性起了至关重 要的作用。前两行主


要是让你现在可以对已经构建的


BeanF actory


的配置做修改,


后面一行就是让你可以对以后再< /p>



创建


Bean


的实例


对象时添加一些自定义的操作。所以他们都是扩展了


Sp ring


的功能,所以我们要学习使用


Spring

< p>
必须对这一部


分搞清楚。



其中在


invokeBeanFactoryPostProcessors


方法中主要是获取实现


BeanFactoryPostProcess or


接口的子类。


并执行它的


post ProcessBeanFactory


方法,这个方法的声明如下:

< br>


清单


ocessBeanFactory



1.



void pos tProcessBeanFactory(ConfigurableListableBeanFactor y beanFactory)



2.





3.



throws BeansException;



它的参数是

< p>
beanFactory


,说明可以对


beanF actory


做修改,这里注意这个


beanFactory< /p>



ConfigurableListableBeanFact ory


类型的,这也印证了前面介绍的不同


BeanFacto ry


所使用的场合不同,这里



只能是 可配置的


BeanFactory


,防止一些数据被用户随意修 改。



registerBeanPostProcessor s


方法也是可以获取用户定义的实现了


BeanPostPro cessor


接口的子类,


并执行


把它 们注册到


BeanFactory


对象中的

beanPostProcessors


变量中。


Bean PostProcessor


中声明



了两个方法:


postProcessBeforeInitialization



postProcessAfterInitializatio n


分别用于在


Bean


对象初始化时执 行。



以执行用户自定义的操作。


< /p>


后面的几行代码是初始化监听事件和对系统的其他监听者的注册,


监听者必须是


ApplicationListener


的子< /p>


类。



如何创建


Bean


实例并构建


Bean


的关系网



下面就是


Bean

< br>的实例化代码,是从


finishBeanFactoryInitializa tion


方法开始的。



清单


BeanFactoryInitialization



1.



protected void finishBeanFactoryInitialization(



2.





3.



ConfigurableListableBeanFactory beanFactory) {



4.





5.





6.





7.



// Stop using the temporary ClassLoader for type matching.



8.





9.



pClassLoader(null);



10.





11.





12.





13.



// Allow for caching all bean definition metadata, not expecting further changes


.



14.





15.



Configuration();



16.





17.





18.





19.



// Instantiate all remaining (non-lazy-init) singletons.



20.





21.



tantiateSingletons();



22.





23.



}



24.





从上面代码中可以发现


Bean


的实例化是在


BeanFactory


中发 生的。


preInstantiateSingletons


方 法的代码


如下:



清单


tantiateSingletons



1.



public void preInstantiateSingletons() throws BeansException {



2.





3.



if (Enabled()) {



4.





5.



(



6.





7.



}



8.





9.



synchronized (finitionMap) {



10.





11.



for (String beanName : finitionNames) {



12.





13.



RootBeanDefinition


bd


=


getMergedLocalBeanDefinition


(bea nName);



14.





15.



if (!ract() && leton()



16.





17.



&& !Init()) {



18.





19.



if (isFactoryBean(beanName)) {



20.





21.



final FactoryBean


factory


=



22.





23.



(FactoryBean) getBean(FACTORY_BEAN_PREFIX+ beanName);



24.





25.



boolean isEagerInit;



26.





27.



if (urityManager() != null



28.





29.



&& factory instanceof SmartFactoryBean) {



30.





31.




isEagerInit


=


Acc essController


.doPrivileged(



32.





33.



&nb sp; new PrivilegedAction



() {



34.





35.



&nb sp; public Boolean run() {



36.





37.



return ((SmartFactoryBean) factory).isEagerInit();



38.





39.



&nb sp; }



40.





41.



}, getAcce ssControlContext());



42.





43.



}



44.





45.



else {



46.





47.




isEagerInit


=


factory


instanceof SmartFactoryBean



48.





49.



&nb sp; && ((SmartFactoryBean) factory).isEagerInit();



50.





51.



}



52.





53.



if (isEagerInit) {



54.





55.



getBean (beanName);



56.





57.



}



58.





59.



}



60.





61.



else {



62.





63.



getBean(beanName);



64.





65.



}



66.





67.



}



68.





69.



}



70.





71.



}



72.





73.



}



74.





这里出现了一个非常重要的


Bean


— —


FactoryBean



可以说< /p>


Spring


一大半的扩展的功能都与这个


Bean


有关,


这是个特殊的


Bea n


他是个工厂


Bean


,可以产生


Bean



Bean


,这里的产生


Bean


是指


Bea n


的实例,如果一个类


继承


Facto ryBean


用户可以自己定义产生实例对象的方法只要实现他的


getObject


方法。然而在


Spring


内部这



Bean


的实例对 象是


FactoryBean


,通过调用这个对象的

< p>
getObject




法就能获取用户自定义产生的对象,从


而为


Spring


提供了很好的扩展性。


Spring


获取


FactoryBean


本身的对象是在前面加上

< br>&


来完成的。



如何创建


Bean


的实例对象以及如何构建


Bean< /p>


实例对象之间的关联关系式


Spring


中的一个核心关键,下面


是这个过程的流程图。






实例创建 流程图



如果是普通的


Bean


就直接创建他的实例,是通过调用


getBean

方法。下面是创建


Bean


实例的时序图:


-


-


-


-


-


-


-


-



本文更新与2021-02-06 02:02,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/604723.html

spring内核详解的相关文章

  • 爱心与尊严的高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊严高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊重的作文题库

    1.作文关爱与尊重议论文 如果说没有爱就没有教育的话,那么离开了尊重同样也谈不上教育。 因为每一位孩子都渴望得到他人的尊重,尤其是教师的尊重。可是在现实生活中,不时会有

    小学作文
  • 爱心责任100字作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任心的作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文