总序
技术服务业务,业务促进技术。
Spring框架
- 首先我们要知道Spring框架是什么?
Spring 是指一个用于构造 JAVA 应用程序的轻量级开源框架框架,
这上面这一句话就概述了Spring框架是什么,就是一个用于构建Java应有程序的轻量级开源框架。
- 这里解释下什么是轻量级?
“轻量级”并不意味着类数量很少,或者发行包大小很小,实际上,它指的是 Spring 设计哲学,那就是最少的侵入。
侵入式:侵入式的做法是要求业务代码”知道”框架的代码,表现为业务代码需要继承框架提供的类,才能很好的和框架结合,使用框架带来的便利。
非侵入式:非侵入式则不需要业务代码引入框架代码的信息,即无需继承框架提供的类,从编写者的角度来看,察觉不到框架的存在。
- Spring框架为什么而生?
-
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。(Enterprise Java Beans)
-
解决企业应用开发的复杂性,使用基本dao的JavaBean代替EJB,并提供了更多的企业应用功能,是java应用变得从简单、可测试和松耦合
- Spring框架解决了什么问题?
◆Spring能有效地组织你的中bai间层对象,无论你是否选du择使用了EJB。如果你仅仅使zhi用了Struts或其他的dao包含了J2EE特有APIs的framework,你会发现Spring关注了遗留下的问题。
◆Spring能消除在许多工程上对Singleton的过多使用。根据我的经验,这是一个主要的问题,它减少了
系统的可测试性和面向对象特性。
◆Spring能消除使用各种各样格式的属性定制文件的需要,在整个应用和工程中,可通过一种一致的方法来进行配置。曾经感到迷惑,一个特定类要查找迷幻般的属性关键字或系统属性,为此不得不读Javadoc乃至源编码吗?有了Spring,你可很简单地看到类的JavaBean属性。倒置控制的使用(在下面讨论)帮助完成这种简化。
◆Spring能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。
◆Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
◆使用Spring构建的应用程序易于单元测试。
◆Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。
◆Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。
■Spring为数据存取提供了一致的框架,不论是使用JDBC或O/R mapping产品(如Hibernate)。
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
Spring整体框架
Spring 总共有十几个组件,但是真正核心的组件只有几个,下面是 Spring 框架的总体架构图:
我们可以看到其中的Core Container中包含了三个重要的组件分别是Bean,Core,Context以及Expression Language。这四个组件,我们现在只需关注其中的Bean,Core,Context组件,因为这三个是构成完整 IOC(Inversion of Control)容器的核心组件
核心组件是如何协同工作的。
-
Bean组件
其中Bean组件是三个组件中最重要的部分,Bean 在 Spring 中作用就像 Object 对 OOP 的意义一样,没有对象的概念就像没有面向对象编程,Spring 中没有 Bean 也就没有 Spring 存在的意义。 -
Context组件
Context组件主要负责给这些数据提供生存环境就,对 Context 来说他就是要发现每个 Bean 之间的关系,为它们建立这种关系并且要维护好这种关系。所以 Context 就是一个 Bean 关系的集合,这个关系集合又叫 Ioc 容器,一旦建立起这个 Ioc 容器后 Spring 就可以为你工作了。 -
Core组件
Core组件就是发现、建立和维护每个 Bean 之间的关系所需要的一些列的工具,从这个角度看来,Core 这个组件就像一个工具包。 -
三者的关系
核心组件详解
Bean组件
这个包下的所有类主要解决了三件事:Bean 的定义、Bean 的创建以及对Bean 的解析。对 Spring 的使用者来说唯一需要关心的就是 Bean 的创建,其他两个由 Spring 在内部帮你完成了,对你来说是透明的。
Bean 的创建
Spring Bean 的创建时典型的工厂模式,它的顶级接口是 BeanFactory,下图是这个工厂的继承层次关系:
BeanFactory下有三个子接口,分别是ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory以及SimpleJndiBeanFactory。
- ListableBeanFactory
ListableBeanFactory 接口表示这些 Bean 是可列表的,它可以枚举所有的bean实例,而不是客户端通过名称一个一个的查询得出所有的实例。要预加载所有的bean定义的beanfactory可以实现这个接口来。 - HierarchicalBeanFactory
HierarchicalBeanFactory 表示的这些 Bean 是有继承关系的,可以作为层次结构的一部分。相对应的bean Factory方法setParentBeanFactory允许在一个可配置beanfactory中设置它们的父bean factory。 - AutowireCapableBeanFactory
AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则,假如它们想要对已经存在的bean暴露它的功能,实现它就能实现自动装配功能。
定义了将容器中的Bean按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法; - SimpleJndiBeanFactory
SimpleJndiBeanFactory是Spring BeanFactory接口的基于jndi的简单实现。不支持枚举bean定义,故不需要实现ListableBeanFactory接口。这个bean工厂可以解析制定名称的jndi名称,在J2EE应用中,jndi名称的命名空间为"java:/comp/env/".
这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。最终的实现类是DefaultListableBeanFactory,实现了所有接口。
spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,他是最简单的容器,只能提供基本的DI功能。因此可以这么说,DefaultListableBeanFactory 是整个spring ioc的始祖。
Bean的定义
Bean 定义的类层次关系图:
Bean 的定义就是完整的描述了在 Spring 的配置文件中你定义的 节点中所有的信息,包括各种子节点。当 Spring 成功解析你定义的一个 节点后,在 Spring 的内部就被转化成 BeanDefinition 对象。以后所有的操作都是对这个对象完成的。
其中AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取
拥有资源获取的能力,也就是读取配置资源的能力。
BeanMatadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。
BeanDefinition主要描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。
Bean的解析
Bean 的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成:
其中XmlBeanDefinitionReader是用来解析Spring的xml配置文件的,再通过BeanDefinitionReader将配置文件解析成Document对象,再通过BeanDefinitionDocumentReader来解析Document对象
Context组件
从上图中可以看出 ApplicationContext 继承了 BeanFactory,这也说明了 Spring 容器中运行的主体对象是 Bean,另外 ApplicationContext 继承了 ResourceLoader 接口,使得 ApplicationContext 可以访问到任何外部资源。
ApplicationContext 的子类主要包含两个方面:
-
ConfigurableApplicationContext: 表示该 Context 是可修改的,也就是在构建 Context 中用户可以动态添加或修改已有的配置信息,所以 ConfigurableApplicationContext 接口的作用就是设置上下文 ID,设置父应用上下文,添加监听器,刷新容器,关闭,判断是否活跃等方法。它下面又有多个子类,其中最经常使用的是可更新的 Context,即AbstractRefreshableApplicationContext 类。
-
WebApplicationContext: 顾名思义,就是为 web 准备的 Context 他允许从相对于web根目录的路劲中装载配置文件完成初始化工作,从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置在ServletContext中,以便web应用可以访问spring上下文,通常情况下,这个接口使用的少。
总体来说 ApplicationContext 必须要完成以下几件事:
- 标识一个应用环境
- 利用 BeanFactory 创建 Bean 对象
- 保存对象关系表
- 能够捕获各种事件
- Context 作为 Spring 的 Ioc 容器,基本上整合了 Spring 的大部分功能,或者说是大部分功能的基础。
Core组件
Core 组件作为 Spring 的核心组件,他其中包含了很多的关键类,其中一个重要组成部分就是定义了资源的访问方式。这种把所有资源都抽象成一个接口的方式很值得在以后的设计中拿来学习。
下图是 Resource 相关的类结构图:
从上图可以看出Resource接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同。对资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,我们看到 Resource 接口继承了 InputStreamSource 接口,这个接口中有个 getInputStream 方法,返回的是 InputStream 类。这样所有的资源都被可以通过 InputStream 这个类来获取,所以也屏蔽了资源的提供者。另外还有一个问题就是加载资源的问题,也就是资源的加载者要统一,从上图中可以看出这个任务是由 ResourceLoader 接口完成,他屏蔽了所有的资源加载者的差异,只需要实现这个接口就可以加载所有的资源,他的默认实现是 DefaultResourceLoader。
Context 和 Resource 的类关系图:
从上图可以看出,Context 是把资源的加载、解析和描述工作委托给了 ResourcePatternResolver 类来完成,他相当于一个接头人,他把资源的加载、解析和资源的定义整合在一起便于其他组件使用。Core 组件中还有很多类似的方式。
Resource与ResourceLoader的关系
1.Resource是包装资源的对象,该接口继承inputstreamSource接口是为继承getinputstream方法,打开一个输入流,Resource对象可以是ClassPathResource、FileSystemResource、UrlResource等
2.ResourceLoader接口就是通过getresource方法来new各种resource对象
3.如果需要按某种匹配方式来new resource对象,所以出现ResourcePatternResolver接口,继承ResourceLoad,增加匹配功能
总结
Spring通过BeanFactory