
.Spring
Spring Framework系统架构
核心概念
- IoC( Inversion of Control )控制反转:使用对象时,不通过程序创建,而是通过在外部的IoC容器直接创建,这种行为叫做控制反转
IoC负责对象的创建、初始化等一一系列的工作,被创建或被管理的对象在IoC容器中被通称为“Bean”
- DI(Dependency Injection)依赖注入
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
就是说两个bean之间有依赖关系DI会自动绑好这个关系
最终效果
使用对象时不仅可以直接从IoC容器中获取,而且获取到的bean已经绑定好了所有依赖关系
IoC和DI基本使用
使用“详情见”
Spring使用
- 在pom.xml中配置
1 | <dependencies> |
- 在resources中右击创建applicationContext.xml
IoC使用
在dao.impl和service.impl中分别创建java类BookDaoImpl.java和BookServiceImpl.java
BookDaoImpl.java
1
2
3
4
5
6public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}BookServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13public class BookServiceImpl implements BookService {
// 5.删除业务层中使用new的方法创建的dao对象
public BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
// 6.提供对应的set方法
public void setBookDao(BookDao bookDao){
this.bookDao=bookDao;
}
}创建接口BookDao和BookService
BookDao
1
2
3public interface BookDao {
public abstract void save();
}BookService
1
2
3public interface BookService {
public abstract void save();
}在applicationContext.xml中添加
配置bean
bean标签表示配置bean
id属性表示给bean起名字
class属性表示给bean定义类型
1 | <bean id="bookDao" class="dao.impl.BookDaoImpl"/> |
- 在运行界面写获取IoC容器
1 | ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); |
- 获取&使用bean
1 | BookDao bookDao=(BookDao) ctx.getBean("bookDao"); |
返回值:book dao save …
DI使用
1 | // 5.删除业务层中使用new的方法创建的dao对象 |
在applicationContext.xml中设置,将bookDao注入bookService
1 |
|
bean配置
bean的基础配置
- 给bean起个别名
name属性:别名,可以定义多个,使用逗号、分号或空格分隔
1 | <bean id="bookDao" name="dao bookDaoiml" class="dao.impl.BookDaoImpl"/> |
- bean作用范围
scope属性:定义bean的作用范围,可选范围如下
singleton:单例(默认) 一个类只有一个实例
prototype:非单例
1 | <bean id="bookDao" name="dao bookDaoiml" class="dao.impl.BookDaoImpl" scope="prototype"/> |
bean实例化方式
通过构造方法实例化
bean本质上就是对象,String创建bean其实是使用构造方法完成的
bean只能默认调用无参构造方法
通过静态工厂实例化bean
静态工厂
1 | public class OrderDaoFactory implements OrderDao{ |
配置
1 | <bean id="orderDao" factory-method="getOrderDao" class="com.demo.factory.OrderDaoFactory"/> |
实例工厂实例化bean
实例工厂
1 | public class OrderDaoFactory implements OrderDao{ |
配置
1 | <bean id="orderDao" class="com.demo.factory.OrderDaoFactory"/> |
第二种实例
实力工厂
1 | public class OrderDaoFactory implements OrderDao{ |
配置
1 | <bean id="orderDao" class="com.demo.factory.OrderDaoFactory"/> |
bean生命周期
初始化容器
创建对象(分配地址)
执行构造方法
执行属性注入(set操作)
执行bean初始化方法
第一种:通过属性值设置生命周期钩子
BookDaoImpl.java
1
2
3
4
5
6
7
8
9
10
11
12public class BookDaoImpl implements BookDao{
public void save() {
System.out.println("book dao save ...");
}
public void init(){
System.out.println("init...");
}
public void destroy(){
System.out.println("destroy...");
}
}applicationContext.xml
1
<bean id="bookDao" class="dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
第二种:通过Spring接口设置生命周期钩子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class BookDaoImpl implements BookDao,InitializingBean, DisposableBean {
public BookDaoImpl(){
}
public void save() {
System.out.println("book dao save ...");
}
public void afterPropertiesSet() throws Exception {
System.out.println("init...");
}
public void destroy() throws Exception {
System.out.println("destroy...");
}
}
属性值注入
在注入时,ref用于引用类型,value用于简单类型
setting注入
为私有属性注入值有两种方式,分别是setting的简单注入,另一个就是使用构造方法
applicationContext.xml
1 | <bean id="bookDao" class="dao.impl.BookDaoImpl"> |
BookDaoImpl.java
1 | private String connectionNumber; |
构造方法注入
applicationContext.xml
index设置构造函数第几个参数
1 | <bean id="bookDao" class="dao.impl.BookDaoImpl"> |
BookDaoImpl.java
1 | private String connectionNumber; |
属性值注入方法选择
用setting注入
- 可选依赖
- 自己开发的推荐使用setting注入
用构造器注入
- 强制依赖
- Spring框架推荐使用构造器方法,且第三方框架基本都是用Spring
自动装配
#所谓自动装配即不用指明两个对象的关系,由Spring自动完成
autowire属性设置使用什么方式进行装配,
byType:通过类型 byName:通过名字
例如:
applicationContext.xml
1 | <bean id="bookDao" class="dao.impl.BookDaoImpl"/> |
注意:
- 自动装配只适用于引用类型,不能对简单类型进行操作
- 推荐使用按类型装配,必须保证容器中相同类型的bean唯一
- 不推荐使用byName,必须保证容器中的bean名称唯一,导致变量名和配置耦合度更高
- 自动装配优先级低于setting和构造方法
BookServiceImpl.java
1 | public class BookServiceImpl implements BookService { |
集合注入
applicationContext.xml
1 | <bean id="bookDao" class="dao.impl.BookDaoImpl"> |
BookDaoImpl.java
1 | public class BookDaoImpl implements BookDao { |
容器
创建容器
方法一:类路径加载配置文件
1 | ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); |
方法二:文件路径加载配置文件
1 | ApplicationContext ctx=new FileSystemXmlApplicationContext("C:\\applicationContext.xml"); |
方法三:加载多个配置文件
1 | ApplicationContext ctx=new FileSystemXmlApplicationContext("bean1.xml","bean2.xml"); |
获取bean
方法一:使用bean名称获取
1 | BookDao bookDao=(BookDao) ctx.getBean("bookDao"); |
方法二:使用bean名获取并获取类型
1 | BookDao bookDao= ctx.getBean("bookDao",BookDao.class); |
方法三:使用bean类型获取
1 | BookDao bookDao= ctx.getBean(BookDao.class); |
核心容器总结
bean
1 | <bean |
依赖注入相关
1 | <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"> |
注解开发定义bean
1 | //使用@component定义bean |
String为了方便开发提供了@component的三个衍生注解
- @Conteoller:用于表现层bean定义
- @Service:用于业务层bean定义
- @Repository:用于数据层bean定义
1 |
|
而当使用三个衍生注解时也不能用单纯的名称了,而是要通过实体类BookDao.class
纯注解开发
在Spring3.0中开启了纯注解开发模式,使用java类来代替配置文件
第一步:删除applcationContext.xml文件
第二步:新建SpringConfig.java配置类
1 | //设置此类为spring配置类 |
第三步:设置加载配置文件类初始化容器
1 | ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class); |
bean的作用范围和生命周期
单例和非单例
1 | //带参数的是设置为非单例 |
生命周期
通过注释@PostConstruct设置初始化
1 |
|
注解依赖注入
引用类型的依赖注入
Service中需要使用dao层:
在dao对象上添加注解@Autowired就会自动匹配
1 | public class BookServiceImpl implements BookService { |
指定匹配注解:@Qualifier(“bookDao”)
注意:@Qualifier要配合@Autowired使用
简单数据类型的依赖注入
1 |
|
使用资源文件为数据添加依赖
资源文件(放置在resources中):
1 | name=ithm888; |
配置类:
1 | //设置此类为Spring配置类 |
Service层:
1 | //将资源文件中的指定值注入 |
注解开发管理第三方bean
在开发时时常会用到第三方的bean,而每一个bean都会有对应的一个专用类管理
例如:
JdbcConfig.java
1 | public DataSource dataSource(){ |
配置类:
1 | //设置此类为Spring配置类 |
运行:
1 | public class run { |
注解开发第三方Bean注入
简单类型
专属配置类中:
1 | public class JdbcConfig { |
引用类型
在注入引用类型时只需要为bean定义方法设置形参
1 | public class JdbcConfig { |
整合——XML和注解开发

AOP
AOP简介
AOP:面向切面编程,一种编程范式,指导开发者如何组织程序结构
作用:在不惊动原始设计的情况下为其进行功能增强
AOP核心概念

AOP入门案例
导入AOP相关依赖
1
2
3
4
5<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>定义dao接口和实现类
1
2
3
4
5
6
7//dao接口
public interface BookDao {
void save();
void update();
void delete();
void select();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23//实现类
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save...");
}
public void update() {
System.out.println("book dao update...");
}
public void delete() {
System.out.println("book dao delete...");
}
public void select() {
System.out.println("book dao select...");
}
}定义通知类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MyAdvice {
//定义切入点,当运行到updata这个方法的时候加功能
private void pt() {
}
//将method添加到上面的切入点pt()中
public void method() {
Long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
System.out.println("success");
}
Long endTime = System.currentTimeMillis();
Long totalTime = endTime - startTime;
System.out.println("执行万次消耗时间" + totalTime + "ms");
}
}定义通知类受Spring容器管理,并定义当前类为切面类
注解@Aspect(上面代码的第二行)
设置Spring对AOP的支持
1
2
3
4
5
public class SpringConfig {
}AOP切入点表达式
可以使用通配符描述切入点,快速描述
- :单个独立的任意符号,可以独立出现,已可以作为前缀或者后缀的匹配符出现
1
execture(public * com.itheima.*.UserService.find*(*))
匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法
.. :多个连续的任意符号,可以独立出现,常用于简化包与参数的书写
1
execture(public User com...UserService.findById(..))
匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法
AOP通知类型
@Before:在原方法之前执行
1 |
|
@After:在原方法之后执行
1 |
|
@Around
1 |
|
AOP通知获取数据
日常使用时,经常会用到给的数值需要通过加工或改变,因此AOP中可以通过切面来进行数据的更改和加工
@Before和@After
1 |
|
@Around
1 |
|
Spring 事务
事务的基本原理
Spring事务的本质其实就是数据库对于事务的支持,当我们使用jdbc时就是利用java.sql.Connection对象完成对事务的提交
事务是一系列的动作,一旦其中有一个动作出现了错误,必须全部回滚。系统将事务中对数据库的所有已完成的操作进行撤销,避免了出现数据不一致而导致的错误。
服务层接口
1 | public interface AccountService { |
JDBC配置类
1 | /*2.在配置类中配置事务管理器*/ |
Spring配置类
1 | /*3.告诉配置类使用注解式事务管理*/ |
事务相关配置
在@Transactional()中写
| 属性 | 作用 | 示例 |
|---|---|---|
| readOnly | 设置是否为只读事务 | readOnly=true 只读事务 |
| timeout | 设置事务超时时间 | timeout=-1(永不超时) |
| rollbackFor | 设置事务回滚异常(class) | rollbackFor={NullPointException.class} |
| propagation | 设置事务传播行为 | …… |
在使用默认是一个出错所有事务都回滚,而这不能满足我们的要求
例如:银行转账模式,当我们取消转账时仍要添加一个日志说明交易取消这就要保证在sql语句不运行的基础上继续通过service层来添加日志
因此,有了设置事务传播行为的枚举
| 传播属性 | 事务管理员 | 事务协调员 |
|---|---|---|
| REQUIRED(默认) | 开启T | 加入T |
| 无 | 新建T2 | |
| REQUIRES_NEW | 开启T | 新建T2 |
| 无 | 新建T2 | |
| SUPPORTS | 开启T | 加入T |
| 无 | 无 | |
| NOT_SUPPORTED | 开启T | 无 |
| 无 | 无 | |
| MANDATORY | 开启T | 加入T |
| 无 | ERROR | |
| NEVER | 开启T | ERROR |
| 无 | ||
| NESTED | 设置savePoint,一旦事务回滚,事务将回滚到savePoint处,交给客户响应提交/回滚 | |
例如:@Transactional(propagation = Propagation.REQUIRES_NEW)