Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您 选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
(1)IOC(控制反转)或DI(依赖注入):明确定义组件的接口,独立开发各个组件,然后根据组件的依赖关系组装运行;即将创建及管理对象的权利交给Spring容器。Spring是一个轻型容器(light-weight Container),其核心是Bean工厂(Bean Factory),用以构造我们所需要的M(Model)。能够让相互协作的软件组件保持松散耦合。降低了业务对象替换的复杂性,提高了组件之间的解耦。
(2)AOP(面向切面编程):通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。即系统级的服务从代码中解耦出来。例如:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来。允许你把遍布应用各处的功能分离出来形成可重用组件。
(1)控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
(2)面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
(3)MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
(4)低侵入式设计,代码污染极低,独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺。
(5)集成能力强:集成多种优秀的开源框架。(Hibernate、Struts、Hessian等)。
(6)异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。
(7)容器:Spring 包含并管理应用中对象的生命周期和配置。
(8)轻量:Spring 是轻量的,基本的版本大约2MB。
(1)CoreContain模块:Core、bean、context、Expression Language。
(2) Data Access/integration(集成)模块:JDBC、ORM、OXM、JMS、Transaction.
(3)Web模块:WEB、Web-Servle、Web-Struts、Web-Portlet。
(4)AOP、Aspects、Instrumentation、Test.
//加载应用上下文
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("ClassPath:spring.xml");
//获取bean
User user = context.getBean("user");
Spring核心组件只有Core、Context、Beans三个。core包侧重于帮助类,操作工具,beans包更侧重于bean实例的描述。context更侧重全局控制,功能衍生。
Bean组件主要解决:Bean 的定义、Bean 的创建以及对 Bean 的解析。
开发者关心Bean创建,其他由Spring内部帮你完成。
(1)Bean 的创建时典型的工厂模式,他的顶级接口是 BeanFactory,下图是这个工厂的继承层次关系:
Bean 工厂的继承关系
BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory。但终的默认实现类是 DefaultListableBeanFactory。实现多接口是为了区分在 Spring 内部操作对象传递和转化时,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。
(2)Bean 的定义主要有 BeanDefinition 描述,如下图说明了这些类的层次关系:
Bean 定义的类层次关系图
Bean 的定义就是完整的描述了在 Spring 的配置文件中你定义的
(3)bean 的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成:
Bean解析类
Context 在 Spring 的 org.springframework.context 包下,给 Spring 提供一个运行时的环境,用以保存各个对象的状态。
ApplicationContext 是 Context 的顶级父类,他除了能标识一个应用环境的基本信息外,他还继承了五个接口,这五个接口主要是扩展了 Context 的功能。下面是 Context 的类结构图:
从上图中可以看出 ApplicationContext 继承了 BeanFactory,这也说明了 Spring 容器中运行的主体对象是 Bean,另外 ApplicationContext 继承了 ResourceLoader 接口,使得 ApplicationContext 可以访问到任何外部资源,这将在 Core 中详细说明。
ApplicationContext 的子类主要包含两个方面:
1.ConfigurableApplicationContext 表示该 Context 是可修改的,也就是在构建 Context 中用户可以动态添加或修改已有的配置信息,它下面又有多个子类,其中最经常使用的是可更新的 Context,即 AbstractRefreshableApplicationContext 类。
2.WebApplicationContext 顾名思义,就是为 web 准备的 Context 他可以直接访问到 ServletContext,通常情况下,这个接口使用的少。
再往下分就是按照构建 Context 的文件类型,接着就是访问 Context 的方式。这样一级一级构成了完整的 Context 等级层次。
总结:
总体来说 ApplicationContext 必须要完成以下几件事:
(1)标识一个应用环境。
(2)利用 BeanFactory 创建 Bean 对象。
(3)保存对象关系表。
(4)能够捕获各种事件。
Context 作为 Spring 的 Ioc 容器,基本上整合了 Spring 的大部分功能,或者说是大部分功能的基础。
Core 组件作为 Spring 的核心组件,他其中包含了很多的关键类,其中一个重要组成部分就是定义了资源的访问方式。这种把所有资源都抽象成一个接口的方式很值得在以后的设计中拿来学习。
从下图可以看出 Resource 接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同。对资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,我们看到:
Resource 相关的类结构图
从上图可以看出 Resource 接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同。对资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,我们看到:
屏蔽资源提供者: Resource 接口继承了 InputStreamSource 接口,这个接口中有个 getInputStream 方法,返回的是 InputStream 类。这样所有的资源都被可以通过 InputStream 这个类来获取,所以也屏蔽了资源的提供者。
资源加载:ResourceLoader 接口完成加载,他屏蔽了所有的资源加载者的差异,只需要实现这个接口就可以加载所有的资源,他的默认实现是 DefaultResourceLoader。
Resource与Context如何建立联系:
从上图可以看出,Context 是把资源的加载、解析和描述工作委托给了 ResourcePatternResolver 类来完成,他相当于一个接头人,他把资源的加载、解析和资源的定义整合在一起便于其他组件使用。Core 组件中还有很多类似的方式。
(1)应用上下文(Application Context)负责装载bean的定义,并把它们组装起来,即装载配置文件。Spring应用上下文全权负责对象的组装。spring自带多种应用上下文的实现,它们之间的区别仅仅在于如何加载配置。
若Spring采用的是xml配置,则选择ClassPathXMLApplicationContext作为应用上下文比较合适。而对于基于java的配置,Spring提供了 AnnotationConfigApplicationContext.加载应用上下文:
(2)Spring自带了多种类型的应用上下文。
a、AnnotationConfigApplicationContext:从一个或多个基于Java配置类中加载Spring应用上下文。
b、AnnotationConfigWebApplicationContext:从一个或多个基于java的配置类中加载Spring Web应用上下文。
c、ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,把应用上下文定义文件作为类资源。
d、FileSystemXMLApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义。
e、xmlWebApplicationContext:从Web应用的一个或多个xml配置文件中加载上下文定义。
//加载应用上下文的几种方式示例
//基于xml的配置
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(“classpath:spring.xml”);
//基于java的配置
AnnotaitionConfigApplicationContext context=new AnnotationConfigApplicationContext(“com.star.config.KnightConfig.class”);
应用上下文准备就绪之后,我们就可以调用上下文的getBean()方法从Spring容器中获取bean。
(1)这个方法就是构建整个 Ioc 容器过程的完整的代码,了解了里面的每一行代码基本上就了解大部分 Spring 的原理和功能了。这段代码主要包含这样几个步骤:(1)构建 BeanFactory,以便于产生所需的“演员”。(2)注册可能感兴趣的事件。 (3)创建 Bean 实例对象。(4)触发被监听的事件。
(2)refresh 也就是刷新配置,前面介绍了 Context 有可更新的子类,这里正是实现这个功能,当 BeanFactory 已存在是就更新,如果没有就新创建。下面是更新 BeanFactory 的方法代码:
https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle。