Spring核心
1.Sping之旅
1.1.简化java开发
为了降低Java开发的复杂性,Spring采取了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入和面向接口实现松耦合;
- 基于切面和惯例进行声明式编程;
- 通过切面和模板减少样板式代码。
1.1.1.依赖注入DI
高度耦合、难以测试的代码
package sia.knights;
public class DamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
this.quest = new RescueDamselQuest();
}
public void embarkOnQuest() {
quest.embark();
}
}
构造器注入的形式,可根据需要传入任何实现了Quest接口的类完成业务逻辑
package sia.knights;
public class BraveKnight implements Knight {
private Quest quest;
public BraveKnight(Quest quest) {
this.quest = quest;
}
public void embarkOnQuest() {
quest.embark();
}
}
SlayDragonQuest是要注入到BraveKnight中的Quest实现,它没有使用System.out.println(),而是在构造方法中请求一个更为通用的PrintStream。
package sia.knights;
public class SlayDragonQuest implements Quest {
private PrintStream stream;
public SlayDragonQuest(PrintStream stream) {
this.stream = stream;
}
public void embark() {
stream.println("Embarking on quest to slay the dragon!");
}
}
创建应用组件之间协作的行为通常称为装配(wiring)。Spring有多种装配bean的方式,采用XML是很常见的一种装配方式。以下程序展现了一个简单的Spring配置文件:knights.xml,该配置文件将BraveKnight、SlayDragonQuest和PrintStream装配到了一起。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="sia.knights.BraveKnight">
<constructor-arg ref="quest" />
</bean>
<bean id="quest" class="sia.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}" />
</bean>
</beans>
以下代码展现了基于Java的配置,它的功能与xml配置相同。
package sia.knights.config;
@Configuration
public class KnightConfig {
@Bean
public Knight knight() {
return new BraveKnight(quest());
}
@Bean
public Quest quest() {
return new SlayDragonQuest(System.out);
}
}
Spring通过应用上下文(Application Context)装载bean的定义并把它们组装起来。Spring应用上下文全权负责对象的创建和组装。Spring自带了多种应用上下文的实现,它们之间主要的区别仅仅在于如何加载配置。
package sia.knights;
public class KnightMain {
public static void main(String[] args) throws Exception {
//加载Spring上下文
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(
"META-INF/spring/knight.xml");//获取配置
//获取bean
Knight knight = context.getBean(Knight.class);
//使用bean
knight.embarkOnQuest();
context.close();
}
}
1.1.2.应用切面
面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。
面向切面编程往往被定义为促使软件系统实现关注点的分离一项技术。系统由许多不同的组件组成,每一个组件各负责一块特定功能。除了实现自身核心的功能之外,这些组件还经常承担着额外的职责。诸如日志、事务管理和安全这样的系统服务经常融入到自身具有核心业务逻辑的组件中去,这些系统服务通常被称为横切关注点,因为它们会跨越系统的多个组件。
package sia.knights;
public class Minstrel {
private PrintStream stream;
public Minstrel(PrintStream stream) {
this.stream = stream;
}
public void singBeforeQuest() {
stream.println("Fa la la, the knight is so brave!");
}
public void singAfterQuest() {
stream.println("Tee hee hee, the brave knight " +
"did embark on a quest!");
}
}
xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="sia.knights.BraveKnight">
<constructor-arg ref="quest" />
</bean>
<bean id="quest" class="sia.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}" />
</bean>
<bean id="minstrel" class="sia.knights.Minstrel">
<constructor-arg value="#{T(System).out}" />
</bean>
<aop:config>
<aop:aspect ref="minstrel">
<aop:pointcut id="embark"
expression="execution(* *.embarkOnQuest(..))"/>
<aop:before pointcut-ref="embark"
method="singBeforeQuest"/>
<aop:after pointcut-ref="embark"
method="singAfterQuest"/>
</aop:aspect>
</aop:config>
</beans>
1.1.3.消除模板样式
如Spring的JdbcTemplate。
1.2.Spring容器
在Spring应用中,对象由Spring容器创建和装配,并存在容器之中。
Spring自带了多种类型的应用上下文。下面罗列的几个是你最有可能遇到的。
- AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文。
- AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
- ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。(在所有的类路径(包含JAR文件)下查找 配置.xml文件)
- FileSystemXmlapplicationcontext:从文件系统下的一个或多个XML配置文件中加载上下文定义。(在指定的文件系统路径下查找 配置.xml文件)
- XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。
bean在Spring容器中的生命周期:
- Spring对bean进行实例化;
- Spring将值和bean的引用注入到bean对应的属性中;
- 如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBean-Name()方法;
- 如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
- 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的
引用传入进来; - 如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessBeforeInitialization()方法;
- 如果bean实现了InitializingBean接口,Spring将调用它们的after-PropertiesSet()方法。类似地,如果bean使用init-method声明了初始化方法,该方法也会被调用;
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialization()方法;
- 此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
- 如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。
1.3.Spring的组成
1.3.1.Spring模块
Spring核心容器
- 容器是Spring框架最核心的部分,它管理着Spring应用中bean的创建、配置和管理。在该模块中,包括了Spring bean工厂,它为Spring提供了DI的功能。基于bean工厂,我们还会发现有多种Spring应用上下文的实现,每一种都提供了配置Spring的不同方式。
- 除了bean工厂和应用上下文,该模块也提供了许多企业服务,例如E-mail、JNDI访问、EJB集成和调度。
- 所有的Spring模块都构建于核心容器之上。当你配置应用时,其实你隐式地使用了这些类。
Spring的AOP模块
- 在AOP模块中,Spring对面向切面编程提供了丰富的支持。这个模块是Spring应用系统中开发切面的基础。
数据访问与集成
- Spring的JDBC和DAO(Data Access Object)模块抽象了访问数据库的样板式代码,在多种数据库服务的错误信息之上构建了一个语义丰富的异常层。
- Spring的ORM模块建立在对DAO的支持之上,并为多个ORM框架提供了一种构建DAO的简便方式。Spring的事务管理支持所有的ORM框架以及JDBC。
- 本模块同样包含了在JMS(Java Message Service)之上构建的Spring抽象层,它会使用消息以异步的方式与其他应用集成。
- 本模块会使用Spring AOP模块为Spring应用中的对象提供事务管理服务。
Web与远程调用
- Spring自带一个功能强大的MVC框架
- Spring远程调用功能集成了RMI(Remote Method Invocation)、Hessian、Burlap、JAX-WS,同时Spring还自带了一个远程调用框架:HTTP invoker。
- Spring还提供了暴露和使用REST API的良好支持。
Instrumentation
- Spring的Instrumentation模块提供了为JVM添加代理(agent)的功能。具体来讲,它为Tomcat提供了一个织入代理,能够为Tomcat传递类文件,就像这些文件是被类加载器加载的一样。
测试
- Spring为使用JNDI、Servlet和Portlet编写单元测试提供了一系列的mock对象实现。
- 对于集成测试,该模块为加载Spring应用上下文中的bean集合以及与Spring上下文中的bean进行交互提供了支持。
1.3.2.Spring Portfolio
整个Spring Portfolio包括多个构建于核心Spring框架之上的框架和类库。概括地讲,整个Spring Portfolio几乎为每一个领域的Java开发都提供了Spring编程模型。
Spring Web Flow | 建立于 Spring MVC 框架之上,它为基于流程的会话式 Web 应用提供支持 |
Spring Web Service | Spring Web Service提供了契约优先的Web Service模型,服务的实现都是为了满足服务的契约而编写的 |
Spring Security | 利用Spring AOP,Spring Security为Spring应用提供了声明式的安全机制 |
Spring Integration | 提供了多种通用应用集成模式的Spring声明式风格实现 |
Spring Batch | 如果需要开发一个批处理应用,你可以通过Spring Batch,使用Spring强大的面向POJO的编程模型 |
Spring Data | 不管你使用文档数据库,如MongoDB,图数据库,如Neo4j,还是传统的关系型数据库,Spring Data都为持久化提供了一种简单的编程模型。这包括为多种数据库类型提供了一种自动化的Repository机制,它负责为你创建Repository的实现 |
Spring Social | Spring Social更多的是关注连接(connect),而不是社交(social)。它能够帮助你通过REST API连接Spring应用,其中有些Spring应用可能原本并没有任何社交方面的功能目标 |
Spring Mobile | Spring MVC新的扩展模块,用于支持移动Web应用开发 |
Spring for Android | 通过Spring框架为开发基于Android设备的本地应用提供某些简单的支持 |
Spring Boot | Spring Boot大量依赖于自动配置技术,它能够消除大部分(在很多场景中,甚至是全部)Spring配置。它还提供了多个Starter项目,不管你使用Maven还是Gradle,这都能减少Spring工程构建文件的大小 |