上一篇文章写了关于maven的入门介绍,本篇读书笔记主要对spring的入门进行介绍一下,主要介绍spring库之间的依赖关系、spring日志在使用时要注意哪些事项、spring在项目中如何进行配置。
Spring介绍
什么是Spring呢?我们看下官方文档给出的答案:
Spring框架是一个轻量级的解决方案,为企业应用开发提供了一站式服务。Spring框架是模块化的,我们在项目开发过程中,只需要使用需要用到的模块,其他的模块则可以不需要,比如我们可以仅使用jdbc模块。Spring框架支持声明式事务管理,可以通过RMI或Web服务远程访问你的业务逻辑,并且提供了许多中持久化解决方案。Spring框架提供了一个全功能的MVC框架,使你能够将AOP透明地集成到你的项目中去。
Spring框架被设计为非侵入性的,带来的好处就是我们项目当中的业务逻辑代码是不依赖于Spring框架本身的。虽然在数据访问层中,存在数据访问层对Spring框架的一些依赖,但是我们很容易把这些依赖关系和我们的业务逻辑代码区分开的。
从上面的介绍中可以看到Spring框架是很强大的,使用起来也非常方便,目前Spring4.x版本提供的jar包已经有20个了,覆盖了我们项目开发当中用到的大部分功能。
Spring每个库的作用以及依赖关系
Spring框架目前包含20个组件,这些组件被分为Core Container、Data Access/Integration、Web、AOP(Aspect Oriented Programming)、Instrumentation、Messaging、Test几大模块。如下图所示:
接下来看下每个库的作用以及它们之间的依赖关系。
Core Container
Core Container包含spring-core、spring-beans、spring-context、spring-context-support、spring-expression组件。
- spring-core和spring-beans组件是框架的基础组成部分,包括Ioc和依赖注入。
- 在spring-beans组件中,BeanFactory实现了一个复杂的工厂模式。
- spring-context组件建立在由core和beans模块提供的实体基础上,spring-context是spring的context上下文即IoC容器。
- spring-context-support支持将常见的第三方库集成到spring应用程序上下文缓存。
- spring-expression提供了强大的表达式语言,用于在运行时查询和操作对象。
它们的依赖关系如图所示:
AOP and Instrumentation
spring-aop模块提供了符合AOP联盟的面向切面的编程实现。spring-aspects集成AspectJ。spring-instrument提供了一些类级的工具支持和ClassLoader的实现,用于服务器。spring-instrument-tomcat针对tomcat的instrument实现。
它们之间的依赖关系如图所示:
Messaging
spring-message包括一个spring消息传递模块。它们的依赖关系如图所示:
Data Access、Integration
- spring-jdbc: jdbc的支持
- spring-tx: 事务控制
- spring-orm: 对象关系映射,集成orm框架
- spring-oxm: 对象xml映射
- Spring-jms: Java消息服务,从spring4.1以后,它提供了与spring-messaging模块的集成。
它们的依赖关系如图所示:
Web
- spring-web: 基础web功能,如文件上传功能,远程支持的Web相关部分。
- spring-mvc: 提供web的mvc功能和Web应用程序的REST Web Service实现。
- spring-webmvc-portlet: 提供了在portlet环境中使用的mvc实现,并反映了基于servlet的spring-webmvc模块的功能。
- spring-websocket: 为web应用提供的高效通信工具。
- spring-struts: 与struts的集成,不推荐,spring4不再提供。
它们的依赖关系如图所示:
Test
spring-test: spring测试,提供JUnit或者TestNG,也提供了Mock测试功能。
它们的依赖关系如图所示:
Spring 4.3版本库有20个,只有搞清楚各个库之间的依赖关系,才能有选择的知道需要引入哪些库,如果使用maven的话,不用去考虑这个问题,maven自动会帮你把依赖的库给搞定的。但搞清楚每个库之间的依赖关系,有助于我们更好理解Spring框架。
Spring日志的使用
日志记录是Spring框架非常重要的依赖,它是唯一的强制性外部依赖关系。从上文中我们知道spring-core组件就依赖于commons-logging日志组件,而其他组件大部分都依赖于spring-core组件,这样整个spring框架都依赖于commons-logging组件了,可以看出spring框架默认依赖的是commons-logging日志组件。
spring框架默认依赖commons-logging组件,但是在实际项目使用中,我们应该避免使用commons-logging组件,因为标准的commons-logging API的运行时算法对于最终的用户是有问题的,想避免commons-logging的标准查找,有两种方法可以解决它。
1、排除spring-core模块的依赖关系,因为它是明确依赖于commons-logging的唯一模块。排除依赖关系的配置如下所示:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.8.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
但是排除之后,必须要用另外一个日志组件来替代它,比如使用SLF4J提供的JCL替代实现。
2、依赖于一个特殊的commons-logging依赖关系,比如SLF4J。SLF4J是Java简单的日志门面,使用日志门面带来的好处就是我们不需要了解具体日志的实现方式,可以绑定到许多常见的日志框架,比如log4j、logback等。用SLF4J代替commons-logging组件有两种方法,第一种方法是依赖于log4j库,第二种方法是依赖于logback库。下面分别介绍这两种方法的配置:
第一种方法是先排除现有对commons-logging的依赖关系,然后配置spring对SLF4J的依赖,SLF4J绑定到log4j,最后提供log4j的jar包。在maven中的配置如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.8.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
第二种方法是对于SLF4J的用户,通常会绑定到Logback来减少生成的依赖关系。因为Logback直接实现了SLF4J,所有只需要依赖两个库,jcl-over-slf4j和logback。maven中的配置如下:
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
</dependencies>
Spring在项目中的配置
Spring在项目中的配置主要分为两步,第一步依赖要使用的spring组件,第二步配置spring.xml文件。第一步比较简单,在maven环境下的配置如下所示:
<!-- 属性配置 -->
<properties>
<spring.version>4.2.5.RELEASE</spring.version>
<!-- 文件拷贝时的编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 编译时的编码 -->
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<!-- spring日志依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
<!-- spring依赖库 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
其中在属性配置的时候,指定了文件拷贝时的编码为UTF-8,编译时的编码也为UTF-8,主要是解决编译时maven2和maven3版本不同的问题。同时在前面也提到使用spring日志框架时应该注意哪些事项,都在配置中有所体现。第二步,首先在web.xml中对dispatcherServlet进行配置,配置如下所示:
<!--springMVC 框架加载服务 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext-springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
其中load-on-startup配置为1,说明服务器启动就立即加载。url-pattern配置为/,说明对所有请求都进行拦截。在init-param初始化参数中,classpath*的作用就是自动定位到maven约定的目录下面,maven约定了哪些目录在我的上篇文章Maven入门介绍中有说到。另外在applicationContext-springmvc.xml文件中对dispatcherServlet的初始化参数有更加详细的配置,applicationContext-springmvc.xml的配置如下所示:
<context:component-scan base-package="com.dodonew.controller"/>
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- 开启静态资源访问 -->
<mvc:default-servlet-handler/>
下面解释一下每条配置的作用是什么?
context:component-scan告诉spring来扫描指定包下的类,并注册被@Component、@Controller、@Service、@Repository等注解标记的组件。
mvc:annotation-driven是告知Spring,我们启用注解驱动,然后Spring会自动为我们注册HandleMapping、HandlerAdapter、ExceptionResolver的相关实例。
task:annotation-driven扫描@Scheduled注解定时器。
mvc:default-servlet-handler也是对静态资源的访问和mvc:resources的作用一样。
参考文章
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/