1. 框架概述
1.1 目的
Spring的主要的目的是简化java开发:
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入和面向接口实现松耦合;
- 基于切面和惯例进行声明式编程;
- 通过切面和模板减少样板式代码
1.2 核心技术
Spring中核心的功能由控制反转和切面编程实现。
1.2.1 控制反转IOC
控制反转(Inversion of Control ,Ioc)
所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护由外部容器来负责。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
依赖注入就是指:在运行期间,有外部容器动态地将依赖对象注入到组件中(构造方法和set方法)
使用IOC的优势是:其降低组件之间的耦合度,实现软件各层之间的解耦.
在Spring中实现依赖注入有xml, javaconfig和annotation三种方式。
1.2.2 AOP
AOP是面向切面的,它使得业务逻辑和非业务逻辑分离,允许你把遍布应用各处的功能分离出来形成可重用的组件。
常用到的场景: 安全,日志,缓存等
面向切面编程往往被定义为促使软件系统实现关注点的分离一项技
术。系统由许多不同的组件组成,每一个组件各负责一块特定功能。
除了实现自身核心的功能之外,这些组件还经常承担着额外的职责。
诸如日志、事务管理和安全这样的系统服务经常融入到自身具有核心
业务逻辑的组件中去,这些系统服务通常被称为横切关注点,因为它
们会跨越系统的多个组件
概念:
通知: 即切面的工作。
Spring切面可以应用5种类型的通知:
- 前置通知(Before):在目标方法被调用之前调用通知功能;
- 后置通知(After):在目标方法完成之后调用通知,此时不会关
心方法的输出是什么; - 返回通知(After-returning):在目标方法成功执行之后调用通
知; - 异常通知(After-throwing):在目标方法抛出异常后调用通知;
- 环绕通知(Around):通知包裹了被通知的方法,在被通知的方
法调用之前和调用之后执行自定义的行为。
切点: 定义了在何处执行通知
切面:切面是通知和切点的结合。通知和切点共同定义了切面的全部内容
——它是什么,在何时和何处完成其功能
织入(Weaving)
织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指
定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点
可以进行织入: - 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译
器。AspectJ的织入编译器就是以这种方式织入切面的。 - 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特
殊的类加载器(ClassLoader),它可以在目标类被引入应用
之前增强该目标类的字节码。AspectJ 5的加载时织入(load-time
weaving,LTW)就支持以这种方式织入切面。 - 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织
入切面时,AOP容器会为目标对象动态地创建一个代理对象。
Spring AOP就是以这种方式织入切面的。
1.2.2 使用
-
编写切点
如下: 其展现了一个切点表达式,这个表达式能够设置党perform方法执行时触发通知。
编写切面:
实现切面的通知之后,然后在通知中添加相应的切点信息即可实现切面的定义。
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
@Before("performance()")
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
1.3 容器
之前的servlet中容器负责servlet的生成,调用和销毁的过程。在基于Spring的应用中,你的应用对象生存于Spring容器(container)中,Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡(在这里,可能就是new到finalize())。
Spring容器并不是只有一个。Spring自带了多个容器实现,可以归为
两种不同的类型。
- bean工厂(由org.springframework. beans.factory.eanFactory接口定义)是最简单的容器,提供基本的DI支持。
- 应用上下文(org.springframework.context.ApplicationContext接口定义)基于BeanFactory构建,并提供应用框架级别的服务,例如从属性文件解析文本信息以及发布应用事件给感兴趣的事件监听者。
spring提供的应用上下文(最可能遇到的):
- AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文。
- AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
- ClassPathXmlApplicationContext:从类路径下的一个或
多个XML配置文件中加载上下文定义,把应用上下文的定义文件
作为类资源。 - FileSystemXmlapplicationcontext:从文件系统下的一个或多个XML配置文件中加载上下文定义。
- XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。
1.4 整体
Spring框架整体包括了核心容器部分,AOP模块部分,数据集成与访问,web与远程调用。
如图所示:
2. Spring web
在先前的servlet的课程中,代码出现的问题:
- 不管servlet还是jsp都将java代码和视图代码在不同程度上耦合在一起了。
- 不能很好的与RESTful API 进行结合。例如请求地址为:user/{userId}
Spring MVC
Spring MVC 是spring相关的web框架项目。其整体的工作流程和机制可以用下图表示:
DispatcherServlet是Spring MVC的核心,其将请求转发给合适的控制器。
对于DispatcherServlet的配置和普通的servlet的配置相同,只不过此时DispatcherServlet是由spring中实现好的。
编写控制器
控制器逻辑上属于控制处理业务逻辑部分,在Spring中以bean的形式出现。所以可以使用@Controller注解来标注该控制器。
@Controller
public class HomeController {
@RequestMapping(value="/", method=GET)
public String home() {
return "home";
}
}
注意点:
- RequestMapping中的value定义了该控制其可以处理的url地址,复杂的可以用正则表达式书写。method表示可以处理的请求必须满足的方法。 其他属性可以参考
- RequestMapping可以定义在类级别
- 函数的参数可以是下面的任何一种:
- 函数的返回值可以是下面的任何一种。
- void
- string: view名称
- HttpEntity
- View
- Map
- Model
- ModelAndView
ViewResolver
spring框架中ViewResolver负责视图的解析工作,ViewResolver的整体的框架如下:(注:实现的ViewResolver未标注完)
不同的视图解析器区别主要在于:面向的视图资源不同。
- InternalResourceViewResolver : 将视图解析为Web应用的内部资源(一般为
JSP) - FreeMarkerViewResolver : 将视图解析为FreeMarker模板
- ContentNegotiatingViewResolver: 通过考虑客户端需要的内容类型来解析视图,委托给另外一个能够产生对应内容类型的视图解析器.
使用视图解析器时需要对其进行配置,如下:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
对于home视图将被解析为:/WEB-INF/jsp/home.jsp
参考: