技术服务业务,业务促进技术。
这上面这一句话就概述了Spring框架是什么,就是一个用于构建Java应有程序的轻量级开源框架。
“轻量级”并不意味着类数量很少,或者发行包大小很小,实际上,它指的是 Spring 设计哲学,那就是最少的侵入。
侵入式:侵入式的做法是要求业务代码”知道”框架的代码,表现为业务代码需要继承框架提供的类,才能很好的和框架结合,使用框架带来的便利。
非侵入式:非侵入式则不需要业务代码引入框架代码的信息,即无需继承框架提供的类,从编写者的角度来看,察觉不到框架的存在。
Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。(Enterprise Java Beans)
解决企业应用开发的复杂性,使用基本dao的JavaBean代替EJB,并提供了更多的企业应用功能,是java应用变得从简单、可测试和松耦合
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
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 的解析。对 Spring 的使用者来说唯一需要关心的就是 Bean 的创建,其他两个由 Spring 在内部帮你完成了,对你来说是透明的。
Spring Bean 的创建时典型的工厂模式,它的顶级接口是 BeanFactory,下图是这个工厂的继承层次关系:
BeanFactory下有三个子接口,分别是ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory以及SimpleJndiBeanFactory。
这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。最终的实现类是DefaultListableBeanFactory,实现了所有接口。
spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,他是最简单的容器,只能提供基本的DI功能。因此可以这么说,DefaultListableBeanFactory 是整个spring ioc的始祖。
Bean 定义的类层次关系图:
Bean 的定义就是完整的描述了在 Spring 的配置文件中你定义的 节点中所有的信息,包括各种子节点。当 Spring 成功解析你定义的一个 节点后,在 Spring 的内部就被转化成 BeanDefinition 对象。以后所有的操作都是对这个对象完成的。
其中AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取
拥有资源获取的能力,也就是读取配置资源的能力。
BeanMatadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。
BeanDefinition主要描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。
Bean 的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成:
其中XmlBeanDefinitionReader是用来解析Spring的xml配置文件的,再通过BeanDefinitionReader将配置文件解析成Document对象,再通过BeanDefinitionDocumentReader来解析Document对象
从上图中可以看出 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 必须要完成以下几件事:
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