Spring框架
Spring
一、Spring 概述
1.1 - 什么是 Spring
是一个开源框架
Spring
是分层的Java SE/EE
应用Full-Stack
轻量级开源框架,以IOC - 反转控制 (Inverse Of Control)
和AOP - 面向切面编程 (Aspecr Oriented Programming)
为内核,提供了展现层Spring MVC
和持久层Spring JDBC
以及业务层事物管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE
企业应用开源框架。
1.2 - Sping 的发展历程
- 1997,
IBM
提出EJB
的思想- 1998,
SUN
制定开发标准EJB1.0
- 1999,
EJB 1.1
发布- 2001,
EJB 2.0
发布- 2003,
EJB 2.1
发布- 2006,
EJB 3.0
发布
Rod Johson ( Spring 之父 )
Expert One-to-One J2EE Design and Development (2002)
阐述了
J2EE
使用EJB
开发设计的优点及解决方案
Expert One-to-One J2EE Development without EJB (2004)
阐述了
J2EE
开发不适用EJB
的解决方案 ( Spring 雏形 )
1.3 - Spring 的优势
方便解耦,简化开发
通过
Spring
提供的Ioc
容器,可以将对象间得到依赖关系交由Spring
进行控制,避免硬编码所在成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用
AOP 编程的支持
通过
Spring
的AOP
工能,方便进行面向切面的编程,许多不容易用传统OOP
实现的功能可以通过AOP
轻松应付
声明式事务的支持
可以将我们从单调烦闷的事物管理代码中解脱出来,通过声明式方式灵活的进行事物的管理,提高开发效率和质量
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情
方便集成各种优秀框架
Spring
可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibermate、Hessian、Quartz
等)的直接支持
降低 JavaEE API 的使用难度
Spring
对JavaEE API
( 如JDBC
、JavaMail
、远程调用等 ) 进行了薄薄的封装层,使这些API
的使用难度大为降低
Java 源码是经典学习范例
Spring
的源码设计精妙,结构清晰,匠心独用,处处体现着对Java
设计模式的灵活运用以及对Java
技术的高深造诣。它的源代码无疑是Java
技术的最佳实践范例
1.4 - Spring 体系结构
Core Container
是
Spring
的核心容器,IoC
部分
1.5 - 耦合
程序间的依赖关系
- 类之间的依赖
- 方法之间的依赖
解耦
降低程序间的依赖关系
应该做到
编译时不依赖
运行时才依赖
解耦的思路
- 使用反射来创建对象,避免使用关键字
new
- 通过读取配置文件,获取要创建的对象全限定类名
1.6 - Bean对象
Bean 在计算机英语中有可重用组件的含义
JavaBean
> 实体类 – 用Java
类编写的可重用组件,就是创建我们的Service
和Dao
- 需要一个配置文件来配置我们的
Service
和dao
- 配置的内容 – 唯一标识=全限定类名( key = value )
- 通过读取配置文件中的信息,反射创建对象
1.7 - 解决技术
Spring 在 JavaEE 的三层结构中,每一层都提供不同的解决技术
- web 层 – SpringMVC
- service 层 – Spring 的 IOC
- dao 层 – Spring 的 JDBCTemplate
二、IOC 控制反转
- 比如有一个类,在类里面有方法(不是静态方法),调用类里面的方法,创建类的对象,使用对象调用方法,创建类对象的过程,需要实例化对象
- 把对象的创建不是通过实例化实现,而是交给
Spring
配置创建类对象
2.1 - IOC 的底层原理
- xml 配置文件
- dom4j 解决 xml
- 工厂设计模式
- 反射
2.1.1 - IOC 的实现
- 将类名写在 xml 文件中
1 <bean id='UserService' class='包名+文件名'/>
- 在工厂中,通过
dom4j
解析xml
文件,通过id
获取到类名
- String className = ‘class属性值’
- 利用反射创建对象
1 Class clazz = Class.forName(ClassName);
- 创建并返回类对象
1 return clazz.newInstance();
2.1.2 - IOC 入门案例
- 导入
jar
包- 创建类,在类里面创建方法
- 创建
Spring
配置文件,配置创建类- 写代码测试对象创建
2.2 - bean 管理
2.2.1 - 实例化的三种方式
- 使用类的无参构造
- 使用静态工厂创建
- 使用实例工厂创建
2.2.2 - Bean 的常用属性
id
– 起名,不得含特殊符号class
– 类的全路径name
– 起名,可有特殊符号scope
– 实例的类型
singleton
– 单例prototype
– 多例requese
– 创建对象把对象放到request
域里面session
– 创建对象把对象放到session
域里面globalSession
– 创建对象把对象放到globalSession
2.3 - 属性注入
2.3.1 - constructor 注入
设有下类
1
2
3
4
5
6
7
8 package 包路径;
public class A {
String key;
public A(String key) {
this.key = key
}
}则在配置文件中应如下所示
1
2
3 <bean id="自定义id" class="包路径.A">
<constructor-arg name="key" value="要赋的值"/>
</bean>
2.3.2 - setter 注入
设有下类,且每个属性都要有对应的 setter 方法
1
2
3
4
5
6
7
8 package 包路径;
public class A {
String key;
public void setKey(String key) {
this.key = key;
}
}则在配置文件中应如下所示
1
2
3 <bean id="自定义id" class="包路径.A">
<property name="key" value="要赋的值"/>
</bean>
2.4 - 对象注入
2.4.1 - constructor 注入
设有以下两个类,B 中有 A 类属性,则 B 类中要有对应的 setter 方法
1
2
3
4
5 package 包路径;
public class A {
}
1
2
3
4
5
6
7
8
9
10 package 包路径;
public class B {
A a;
public B(A a) {
this.a = a;
}
}则在配置文件中应如下所示
1
2
3
4 <bean id="a" class="包路径.A"/>
<bean id="b" class="包路径.B">
<constructor-arg name="a" ref="a"/>
</bean>
2.4.2 - setter 注入
设有以下两个类,B 中有 A 类属性,则 B 类中要有对应的 setter 方法
1
2
3
4
5 package 包路径;
public class A {
}
1
2
3
4
5
6
7
8
9
10 package 包路径;
public class B {
A a;
public void setA(A a) {
this.a = a;
}
}则在配置文件中应如下所示
1
2
3
4 <bean id="a" class="包路径.A"/>
<bean id="b" class="包路径.B">
<property name="a" ref="a"/>
</bean>
2.6 - IOC 和 DI 的区别
IOC
:控制反转,把对象创建交给spring
进行配置DI
:依赖注入,向类里面的属性中设置值- 依赖注入不能单独存在,需要在
IOC
基础之上完成操作
2.7 - 注解创建对象
2.7.1 - 注解
第一步:引入约束
1
2 http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd第二步:添加到配置文件
1
2 <context:component-scan base-package="包路径"/>
<context:annotation-config/>
- @Component()
用于创建对象,取的名字在括号中赋值给
value
- @Controller()
Component
的衍生,用于web
层
- @Service()
Component
的衍生,用于业务层
- @Repository()
Component
的衍生,用于持久层
- @Scope()
功能和配置文件里的
Scope
一样,值在括号中赋值给value
- @Autowired
自动注入其下的属性
- @Resource()
自动注入属性,在括号中通过
name
指定对应的bean
,更准确,更常用
- @Aspect
用于增强所在类
- @Before()
前置增强
- @AfterReturning()
后置增强
- @Around()
环绕增强
- @AfterThrowing()
异常增强
- @After()
最终增强
- @Transactional
事务增强
2.7.2 - 使用注解创建对象
1
2
3
4
public class A {
}就可以用
getBean("a")
创建对象了
2.7.3 - 使用注解注入属性
设有 A 类
1
2
3
4
5
6 package 包路径;
public class A{
}写入配置
1
2 <bean id="自定义id" class="包路径"/>
- 使用 @Autowired 注入
设有 B 类
1
2
3
4
5 public class B {
A a;
}在属性上方加上
@Autowired
注解即可
- 使用 @Resource 注入
设有 B 类
1
2
3
4
5 public class B {
A a;
}
三、AOP 思想
3.1 - 相关术语
JoinPoint - 连接点
类里面哪些方法可以被增强
PointCut - 切入点
被增强了的方法
Advice - 通知/增强
增强的逻辑,增加一个什么功能
- 前置增强 – 在切入点之前执行
- 后置增强 – 在切入点之后执行
- 异常增强 – 在切入点出现异常时执行
- 最终增强 – 在后置增强之前执行
- 环绕增强 – 在切入点之前和之后执行
Aspect - 切面
把增强应用到切入点的过程
Introduction - 引介
在不修改类的代码的前提下,可以在运行期动态的添加一些方法
Target - 目标对象
要增强的类
Weaving - 织入
把增强应用到目标的过程
Proxy - 代理
一个类被
AOP
织入增强后,就产生一个结果代理类
3.2 - AspectJ
用来实现
AOP
操作
AspectJ
不是Spring
的一部分
3.4 - 环境准备
引入约束
1
2
3 http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
3.3 - 配置文件实现 AOP
有如下两个类
1
2
3
4
5
6
7 package 包路径;
public class A {
public void front() {
}
}
1
2
3
4
5
6
7 package 包路径;
public class B {
public void met() {
}
}在
xml
中配置如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 <aop:config>
// 配置切入点
<aop:pointcut id="切入点名称" expression="execution(* *.*())"/>
// 配置切入面
<aop:aspect ref="增强所在类的 bean-id">
// 配置增强的方法,其中 method 指用哪个类来增强,pointcut-ref 指切入点
<aop:before method="front" pointcut-ref="切入点名称"/>
</aop:aspect>
</aop:config>
- execution(* *.*(..)) 表达式
- 第一个 * 号是返回类型
- 第二个 * 号是切入点所在类的全路径
- 第三个 * 号是切入点
3.5 - 注解方式实现 AOP
添加至
xml
配置文件
1
2 <aop:aspectj-autoproxy/>有下面两个类
1
2
3
4
5
6
7
8
9 package 包路径;
public class A {
public void front() {
}
}
1
2
3
4
5
6
7 package 包路径;
public class B {
public void met() {
}
}
四、JDBC Template
4.1 - 环境配置
4.1.1 - 导入 jar 包
c3p0
mysql-connector-java
mchange-commons-java
4.1.2 - 配置连接池
在 xml
中配置
1 | <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> |
4.1.3 - 配置 JDBC Template
在 xml
中配置,并注入 dataSource
1 | <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> |
4.1.4 - 配置 Dao
新建类,定义
JdbcTemplate
,设置 setter 方法
1
2
3
4
5
6
7
8
9 package 包路径;
public class A {
private JdbcTemplate jdbc;
public void setJdbc(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
}利用
xml
配置文件注入
1
2
3
4 <bean id="自定义" class="包路径.A">
<property name="jdbc" ref="jdbcTemplate"/>
</bean>
4.2 - 增
1 | String sql = "insert into 表名 values(···)"; |
4.3 - 删
1 | String sql = "delete from 表名 where 条件"; |
4.4 - 查
4.4.1 - 查询某一个返回值
1 | String sql = "select count(*) from 表名"; |
4.4.2 - 查询后将一行结果封装到一个对象
1 | String sql = "select * from 表名 where 条件"; |
结果类需自己写
1 | public class 映射类 implements RowMapper<结果类> { |
4.4.2 - 查询后将一行结果封装到一个列表
1 | String sql = "select * from 表名 where 条件"; |
结果类需自己写
1 | public class 映射类 implements RowMapper<结果类> { |
4.5 - 改
1 | String sql = "update 表名 set 字段名 = ? where 条件"; |
4.6 - 事务管理
4.6.1 - 环境配置
- 引入约束
1 | http://www.springframework.org/schema/tx |
4.6.2 - 配置文件方式
- 创建事务管理器
1 | <bean id="管理器名称" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
- 配置事务增强
1 | <tx:advice id="增强名称" transaction-manager="管理器名称"> |
- 配置切面
1 | <aop:config> |
4.6.3 - 注解方式
- 配置事务管理器
1 | <bean id="管理器名称" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
- 开启事务注解
1 | <tx:annotation-driven transaction-manager="transactionManager"/> |
- 使用
在需要事务管理的类上面加上注解 @Transactional
1 |
|