一、@Aspectj注解配置切面编程
1.1. 搭建环境
1. Spring基本包(4+2: beans,context,core,expression + logging+log4j)
2. aop编程导入aop相关的包(2+2 : aop联盟,aspectj,aop联盟整合包,aspectj整合包)
3. Spring-Junit测试:test
--------------------------------------------------------------------------
4. 导入log4j.properties日志配置文件,导入含有beans,context,aop约束的applicationContext.xml
1.2. 使用注解完成aop编程
1. 确定目标对象,注册bean
2. 编写增强类,注册bean
3. 使用注解配置切面和切入点
4. 测试
目标对象:UserServiceImpl / ProductService
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
// 使用Spring的AOP编程增强
public void save() {
System.out.println("用户注册.........");
}
}
//没有接口的目标对象bean
@Service
public class ProductService {
//模拟添加商品..对该方法进行增强
public void save() {
System.out.println("ProductService.......添加商品...........");
}
}
并在两个目标对象上使用@Service完成了bean的注解
---------------------------------------------------------------------------
编写增强类,注册bean(MyAspect):
//通知/增强类,对切入点进行增强
@Component //注册bean,将增强类交给Spring管理
@Aspect //将该类标识为切面类(该类里面有增强方法),相当于
public class MyAspect {
//前置增强,参数value:写切入点表达式
//相当于
@Before("bean(*Service)")
public void writeLog() {
System.out.println("开始写日志了......Spring..aop开发");
}
}
-----------------------------------------------------------------------------
到这里,目标bean的定义,增强类的定义以及切面的配置完成,但是还需要在核心配置文件中开启注解扫描与自动代理机制。
-----------------------------------------------------------------------------
测试:
@RunWith(SpringJUnit4ClassRunner.class)//Spring整合Junit
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringTest {
//注入测试bean
@Autowired
@Qualifier("userService")
private UserService userService;
@Autowired
private ProductService productService;
@Test
public void test() {
userService.save();
System.out.println("======================");
productService.save();
}
}
补充:
我们的aop代理是使用的Spring的内部代理机制,默认是如果有接口就优先对接口代理(jdk动态代理)。
问题:如果目标对象有接口,能否只对实现类代理,而不对接口进行代理?可以!
这里要使用子类的扩展方法,而接口中没有该方法,因为代理对象与目标对象不能互转,所以不能调用。
这时可以使用类代理(cglib动态代理),只需要设置 proxy-target-class = true
1.3. 使用@Pointcut 定义切入点
问题:如果直接在通知注解中写切入点表达式,会发生重复编写,后期不便于维护
解决:
在实际开发中,切入点都是单独定义维护的,如:
* 使用xml定义切入点
* 使用注解单独定义切入点@Pointcut
语法要求:
切点方法:private void 无参数方法,方法名为切点名
=============================================================================
//通知/增强类,对切入点进行增强
@Component
@Aspect
public class MyAspect {
// 定义切入点,id/name就是方法名
// 优点:方便统一维护
@Pointcut("bean(*Service)") // 定义切入点表达式
private void myPointcut() {
}
// @Before("bean(*Service)")
// 建立切入点与通知之前的关联,完整类名.方法名
// @Before("com.itdream.spring.aopanno.MyAspect.myPointcut()")
@Before("myPointcut()") // 因为在类的内部,可简写
public void writeLog() {
System.out.println("开始写日志了......Spring..aop开发");
}
}
测试结果:
另外,一个通知方法也可以对多个切入点进行增强:
二、Spring JdbcTemplate模板类
2.1 概述
Spring中有一系列XxxTemplate类,这些类主要是用于简化xxx的编程。
Spring JdbcTemplate 是一个模板工具类,简化Jdbc编程 (类似 Apache DbUtils )
JdbcTemplate 简化 jdbc编程
HibernateTemplate 极大的简化 Hibernate编程
2.2 JdbcTemplate快速入门-代码
目标:使用Jdbc Template操作数据库。
1. 搭建环境
1. 4+2个Spring基本jar包:beans,core,context,expression+logging,log4j.
2. 导入JDBC模板开发包(2个):spring-jdbc.jar , spring-tx.jar ,有耦合性,因此操作jdbc需要导入tx,操作事务需要导入jdbc
3. 导入测试包:spring-test.jar
4. 数据库驱动
5. 导入log4j.properties配置文件和核心配置文件applicationContext.xml
2. 代码
1. 编写Service层、dao层操作数据库
===========================================================================
dao层:
public class UserDAO {
//使用jdbc Template模板类操作数据库
public void create() {
//创建数据源(连接数据库),内置连接池,不建议生产环境下使用
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUsername("root");
dataSource.setPassword("root");
//创建JdbcTemplate模板对象,简化JDBC代码
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//设置数据源(连接池)
jdbcTemplate.setDataSource(dataSource);
jdbcTemplate.execute("create table user001 (name varchar(20))");
}
}
service层:
public class UserService {
//业务层,调用dao层
public void create() {
UserDAO userDAO = new UserDAO();
userDAO.create();
}
}
以上是使用JdbcTemplate操作数据库的基本方式。
2.3. JdbcTemplate的XML配置方式
目标:将数据源和jdbcTemplate都交给Spring来管理。
这里还是使用Spring的内置的连接池。
applicationContext.xml:
注意:
UserDAO中提供JdbcTemplate的声明以及setter方法,以供属性注入。
UserService中提供UserDAO的声明以及setter方法,以供UserDAO注入。
测试:
@RunWith(SpringJUnit4ClassRunner.class)//整合Spring与Junit
@ContextConfiguration(locations="classpath:applicationContext.xml")//为Spring容器指定配置文件
public class SpringTest {
@Autowired
private UserService userService;
@Test
public void test() {
userService.create();
System.out.println("建表成功");
}
}
2.4 使用JdbcDaoSupport简化开发
上面我们使用xml配置,将数据源,模板类,UserDAO以及UserService交给了Spring管理,但是配置文件中写的代码有点多。
Spring提供了JdbcDaoSupport来方便Dao中注入Jdbc Template.
我们只需要继承JdbcDaoSupport,将这个dao类注册成bean,注入dataSource数据源即可。
它会调用父类JdbcDaoSupport的setDataSource方法,将注入的DataSource传入,返回一个JdbcTemplate
因此,我们在dao类中,直接获取父类配置了注入数据源的JdbcTemplate使用即可
============================================================================
userDAO:(之前定义用于注入的JdbcTemplate代码就节省了)
public class UserDAO extends JdbcDaoSupport {
// Spring注入的DataSource会调用父类JdbcDaoSupport中的setDataSource方法
// 该方法会return new JdbcTemplate(dataSource);这个dataSource就是配置文件中注入的dataSource\
// 因此父类中就有了一个配置了注入数据源的JdbcTemplate,我们直接get父类的JdbcTemplate模板类使用即可
// 使用jdbc Template模板类操作数据库
public void create() {
getJdbcTemplate().execute("create table user002 (name varchar(20))");
}
}
UserService:
public class UserService {
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
// 业务层,调用dao层
public void create() {
userDAO.create();
}
}
--------------------------------------------------------------------------
配置文件applicationContext.xml:(不需要注册JdbcTemplate,直接向DAO中注入数据源dataSource即可)
测试:
2.4 配置自定义连接池
2.4.1 DBCP连接池的配置
1.导入DBCP连接池所需的jar包(tomcat内置了apache dbcp的jar包)
commons-pool-1.5.6.jar commons-dbcp-1.4.jar
2. 配置DBCP连接池(根据setter方法确定name)
DBCP连接池的配置与Spring内置连接池的配置几乎一模一样,修改一下class即可。
2.4.2 C3P0连接池的配置
1.导入C3P0连接池所需的jar包
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
2. 配置DBCP连接池(根据setter方法确定name)
2.5. 外部属性文件的引入配置
上面我们进行了数据源(连接池)在Spring中的配置,我们有时候需要更换连接池,而配置文件的代码很多,修改起来不方便,因此将它的参数提取出来放在一个配置文件中。
模拟需求:
现在数据源的相关参数配置,是测试环境下的。
现在,要将工程搭建在正式的服务器上,因为测试环境和正式环境的数据库肯定不是一个。
所以肯定首先要更改数据源相关的配置。将数据源相关配置参数,外置。
目的:可以将xml配置中可能要经常修改内容,抽取到一个properties文件
应用:使用properties文件配置参数,如数据库连接参数等。
------------------------------------------------------------------------------
1. 从applicationContext.xml中抽取经常修改的变量
例如:
jdbc.dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
2. 在applicationContext.xml中读取抽取出去的变量
首先要使用context:property-placeholder标签引入外界配置文件。
1. 因此首先要导入,context有关的schema约束。
2. 引入外界配置文件设置
3. 引入变量
............................
2.6. 使用Jdbc Template进行CRUD操作
ProductDAO :
//使用JDBC Template进行CRUD操作
public class ProductDAO extends JdbcDaoSupport {
// 继承了JdbcDaoSupport类,不需注入JdbcTemplate,只需要注入DataSource连接池即可
// DAO中注入连接池DataSource,Spring会找到父类中的setDataSource,从而创建一个配置了注入连接池的JdbcTemplate
// 因此在这里,我们可以直接调用父类的getJdbcTemplate()方法即可
// 增加商品
public void save(Product product) {
String sql = "insert into product values(null,?,?)";
getJdbcTemplate().update(sql, product.getPname(), product.getPrice());
}
// 删除商品
public void delete(Product product) {
String sql = "delete from product where pid=?";
getJdbcTemplate().update(sql, product.getPid());
}
// 修改商品
public void update(Product product) {
String sql = "update product set price=? where pid=?";
getJdbcTemplate().update(sql, product.getPrice(), product.getPid());
}
// 投影查询
public Object findNameById(int pid) {
String sql = "select pname from product where pid=?";
return getJdbcTemplate().queryForObject(sql, new SingleColumnRowMapper<>(), pid);
}
// 投影查询
public Object findColumnsById(int pid) {
String sql = "select pname,price from product where pid=?";
return getJdbcTemplate().queryForObject(sql, new ColumnMapRowMapper(), pid);
}
// 查询单个商品
public Product query(int pid) {
String sql = "select * from product where pid=?";
return getJdbcTemplate().queryForObject(sql, new BeanPropertyRowMapper<>(Product.class), pid);
}
// 查询多商品
public List queryProducts(String pname) {
String sql = "select * from product where pname like ?";
return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(Product.class), "%" + pname + "%");
}
//查询所有商品
public List findAll() {
String sql = "select * from product";
return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(Product.class));
}
}
---------------------------------------------------------------------------
配置文件applicationContext.xml:
---------------------------------------------------------------------------
测试:
@RunWith(SpringJUnit4ClassRunner.class) // 整合Spring,否则不能注入测试bean
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringTest {
@Autowired
private ProductDAO productDAO;
@Autowired
private Product product;
@Test
public void test() {
// productDAO.save(product);
// productDAO.delete(product);
// product.setPid(2);
// product.setPrice(2999D);
// productDAO.update(product);
System.out.println(productDAO.findNameById(2));
System.out.println(productDAO.findColumnsById(2));
System.out.println(productDAO.query(2));
System.out.println(productDAO.queryProducts("one"));
System.out.println(productDAO.findAll());
}
}
=============================================================================
总结:
- 增删改的操作使用update
- 简单查询使用```queryForObject````查询
- 封装单个对象使用
BeanPropertyRowMapper
封装 - 投影查询对象属性使用
ColumnMapRowMapper
- 封装单个对象使用
- 复杂的查询使用
query
查询- 封装使用
new BeanPropertyRowMapper
封装
- 封装使用
三、 Spring的事务管理机制【了解】
Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的:
- PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理
- TransactionDefinition: 事务定义信息(隔离、传播、超时、只读)—通过配置如何进行事务管理。
- TransactionStatus:事务具体运行状态—事务管理过程中,每个时间点事务的状态信息。
3.1. PlatformTransactionManager事务管理器
该接口提供三个方法:
- commit : 提交事务
- rollback : 回滚事务
- getTransaction : 获取事务状态
Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现:
-
DataSourceTransactionManager
针对JdbcTemplate、MyBatis
事务控制 ,使用Connection
(连接)进行事务控制 :-
connection.setAutoCommit(false)
:开启事务 -
connection.rollback()
:回滚事物 -
connection.commit()
:提交事物
-
-
HibernateTransactionManager
针对Hibernate
框架进行事务管理, 使用Session的Transaction
相关操作进行事务控制 :-
session.beginTransaction()
:开启事务 -
session.getTransaction.commit
:提交事务 -
session.getTransaction.rollback
:回滚事务
-
根据选择和使用的持久层技术,来选择对应的事务管理器。
3.2. TransactionDefinition事务定义信息
该接口主要提供的方法:
-
getIsolationLevel
:隔离级别获取 -
getPropagationBehavior
:传播行为获取 -
getTimeout
:获取超时时间(事务的有效期) -
isReadOnly
: 是否只读。事务管理器能够根据这个返回值进行优化。- 保存、更新、删除—对数据进行操作-设置为false(默认值),变成可读写的,
- 查询-设置这个属性为true,只能读不能写)
这些事务的定义信息,都可以在配置文件中配置和定制。
3.2.1. IsolationLevel事务的隔离级别
Spring使用默认的defalut:根据数据库的默认隔离级别确定
* MySQL的默认隔离级别是Repeatable_Read,可重复读
* Oracle的默认隔离级别是Read_Commit,读已提交
3.2.2. 事务的传播行为Transaction Propagation Behavior
事务传播行为用于解决两个被事务管理的方法互相调用问题
业务层两个方法面临的事务问题:有些时候需要处于同一个事务,有些时候不能在同一个事务 !
事务的传播行为的7种类型:
有关事务传播行为的详细解释:
PROPAGATION_REQUIRED(默认值)
A中有事务,使用A中的事务.如果A中没有,B就会开启一个新的事务,将A包含进来.(保证A,B在同一个事务中),默认值!!
PROPAGATION_SUPPORTS
A中有事务,使用A中的事务.如果A中没有事务.那么B也不使用事务.
PROPAGATION_MANDATORY
A中有事务,使用A中的事务.如果A没有事务.抛出异常.
PROPAGATION_REQUIRES_NEW
A中有事务,将A中的事务挂起.B创建一个新的事务.(保证A,B没有在一个事务中)
PROPAGATION_NOT_SUPPORTED
A中有事务,将A中的事务挂起.
PROPAGATION_NEVER
A中有事务,抛出异常.
PROPAGATION_NESTED
嵌套事务.当A执行之后,就会在这个位置设置一个保存点.如果B没有问题.执行通过.如果B出现异常,运行客户根据需求回滚
为方便记忆,将Spring的事务传播行为分为三大类:
**PROPAGATION_REQUIRED(默认值)**、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY
支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务 。
事务默认传播行为 REQUIRED。最常用的。
**PROPAGATION_REQUIRES_NEW**、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER
不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务。
常用的事务传播行为:PROPAGATION_REQUIRES_NEW
**PROPAGATION_NESTED**
嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点
面试题: REQUIRED、REQUIRES_NEW、NESTED 区分?
REQUIRED 一个事务(默认,推荐)
REQUIRES_NEW 两个事务
NESTED 一个事务,事务可以设置保存点,回滚到保存点 ,选择提交或者回滚
3.3. TransactionStatus 事务状态
-
flush(),给hibernate
使用,底层发出sql的 -
hasSavepoint()
:判断是否有保留点 -
isCompleted()
:判断事务是否结束 -
isNewTransaction()
:判断当前事务是否是新开的一个事务。 -
isRollbackOnly()
:判断事务是否只能回滚 -
setRollbackOnly()
:设置事务是否回滚
数据库操作中,如果只是回滚,后面不操作,数据库在关闭连接的时候,自动发出了commit。commit结束事务。
三个事务超级接口对象之间的关系:
- 用户管理事务,需要先配置
TransactionDefinition
(事务定义信息、事务的管理方案); - 然后根据
TransactionDefinition
,通过TransactionManager
(事务管理器)进行事务管理; - 事务运行过程中,每个时刻都可以通过获取
TransactionStatus
(事务状态)来了解事务的运行状态。
3.4. Spring事务管理两种方式
- 编程式的事务管理(有侵入性,很少用)
- 使用XML或注解配置声明式事务【开发中使用】
- Spring的声明事务通过AOP实现(环绕通知)
3.4.1 使用XML配置声明式事务
示例:
需求:
银行转账:转出、转入,使用Spring的声明式事务
-------------------------------------------------------------------------
步骤:
1. 搭建环境
1. 导入jar包
Spring基本包:4+2 : beans,context,core,expression. + apache logging,log4j
spring测试包: test
spring事务包: tx,jdbc(jdbc与tx有耦合,使用其中一个包必须导入另一个)
spring的事务依赖AOP(2+2):apache-aop联盟,aspect. spring对两个包的整合包
数据库驱动:mysql-converter
c3p0连接池的jar包
--------------------------------------------------------------------
2. 导入log4j.properties配置文件,applicationContext.xml配置文件
3. 完成数据库建表以及模拟的两个用户
4. 根据表编写实体类User
2. 完成功能
1. 编写UserDAO的转入转出数据库操作(使用JdbcTemplate)
2. 编写UserService完成业务逻辑操作
3. 完成事务增强
1. 确定目标类,注册bean
2. 注册增强类
3. 配置切面和切入点(切入点和通知之间的关联)
3. 测试
===========================================================================
1. 搭建环境:
jar包:
创建数据库表user:
CREATE DATABASE spring;
CREATE TABLE USER(
uid INTEGER PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
acount DOUBLE
);
INSERT INTO USER VALUES(NULL,'tom',1000),(NULL,'jack',1000);
创建实体类User:
//User的实体类
public class User {
private Integer uid;
private String username;
private Double acount;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Double getAcount() {
return acount;
}
public void setAcount(Double acount) {
this.acount = acount;
}
@Override
public String toString() {
return "User [uid=" + uid + ", username=" + username + ", acount=" + acount + "]";
}
}
导入log4j.properties,applicationContext.xml核心配置文件。
2. 业务实现:
UserDAO:
//模拟银行转账
public class UserDAO extends JdbcDaoSupport {
// 注入dataSource父类会自动创建一个配置了注入数据源的JdbcTemplate
// 转出
public void out(String outname, Double money) {
String sql = "update user set acount=acount-? where username=?";
getJdbcTemplate().update(sql, money, outname);
}
// 转入
public void in(String inname, Double money) {
String sql = "update user set acount=acount+? where username=?";
getJdbcTemplate().update(sql, money, inname);
}
}
UserService:
public class UserService {
// 注入userDAO
private UserDAO userDAO;
// 提供setter方法
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void transfer(String outname, String inname, Double money) {
//开启事务
//转出
userDAO.out(outname, money);
//制造异常
//int i = 1/0;
//转入
userDAO.in(inname, money);
//关闭事务
}
}
---------------------------------------------------------------------------
配置applicationContext.xml完成Spring的声明式事务:
头约束:
因为JdbcTemplate和事务管理器都需要导入数据源,因此配置了c3p0连接池,抽取了变量另外配置。
为了能引入外部配置,使用context..placeholder,需要引入context头约束。
因为要使用事务,因此需要导入aop和tx的头约束(spring的事务依赖aop的环绕通知完成)
外部数据源的配置(db.properties):
jdbc.dataSourceClass=com.mchange.v2.c3p0.ComboPooledDataSource
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
核心配置文件(applicationContext.xml):
---------------------------------------------------------------------------
测试:
@RunWith(SpringJUnit4ClassRunner.class)//整合Spring进行测试
@ContextConfiguration(locations="classpath:applicationContext.xml")//为Spring容器指定配置文件
public class SpringTest {
@Autowired
//注入测试bean
private UserService userService;
@Test
public void testTransfer() {
//tom向jack转账1000元
userService.transfer("tom", "jack", 100D);
System.out.println("转账成功.............");
}
}
3.4.2 使用注解配置声明式事务
步骤:
1. 确定目标类,方法(要被增强的方法,即切入点),注册bean
2. 确定增强类(这里要完成事务管理),Spring已经帮我们实现了
3. 配置切面关系(注解实现),在需要管理事务的方法或者类上面 添加@Transactional 注解
4. 配置注解驱动事务管理(事务管理注解生效的作用)(需要配置对特定持久层框架使用的事务管理器)
-----------------------------------------------------------------------------
1. @Service将目标类 UserService注册成bean
2. Spring已经帮我们实现了事务管理的增强类,无需手动实现并注册了
3. 配置切面关系,@Transactional写在需要增强的方法或类上
@Service("userService")
public class UserService {
// 注入userDAO
@Autowired
@Qualifier("userDAO")
private UserDAO userDAO;
//在需要管理事务的方法或类上面用@Transactional管理
@Transactional
public void transfer(String outname, String inname, Double money) {
//转出
userDAO.out(outname, money);
//制造异常
//int i = 1/0;
//转入
userDAO.in(inname, money);
}
}
----------------------------------------------------------------------------
需要将UserDAO也注册成bean,将DataSource数据源传入,调用父类setDoataSource方法,创建一个JdbcTemplate,
这样UserDAO就可以直接获取父类的JdbcTemplate使用了。
但是,如果将@Autowired直接注解声明的对象上,Spring会自动创建一个setDataSource()方法,与父类的final冲突。
因此自己定义一个set方法接收DataSource,调用父类的setDSataSource方法。
@Repository("userDAO") // 将其注册成bean
public class UserDAO extends JdbcDaoSupport {
//使用注解@Autowired注入DataSource数据源会默认生成setter方法,setDataSource(Datasource ds)注入
//但是父类的setDataSource是用final修饰的,不能重写,而且这样也无法将dataSource传入到setDataSource方法中
//这样就无法生成配置了注入数据源的JdbcTemplate,因此我们随便写一个set方法,参数类型写DataSource调用父类的setter方法
//@Autowired
//private DataSource dataSource;
@Autowired
public void setSuperDataSource(DataSource dataSource) {
super.setDataSource(dataSource);
}
// 转出
public void out(String outname, Double money) {
String sql = "update user set acount=acount-? where username=?";
getJdbcTemplate().update(sql, money, outname);
}
// 转入
public void in(String inname, Double money) {
String sql = "update user set acount=acount+? where username=?";
getJdbcTemplate().update(sql, money, inname);
}
}
4. 配置注解驱动事务管理器
-------------------------------------------------------------------------
1. 事务的相关策略:
isolation,read-only...可以直接在@Transactional后配置
2. 如果在类上标识@Transactional,那么会对该类中的所有public方法都包装事务,等同于所有的public方法上面
都添加了@Transactional。
如果某个方法需要单独的事务定义,需要在方法上加@Transactional来覆盖类上的标注声明。
xml和注解的选择:
XML方式,集中式维护。使用XML进行事务管理 属性集中配置,便于管理和维护
注解方式,使用@Transactional注解进行事务管理,配置太分散
因此优选使用XML进行事务管理。
事务的策略通配符设置:
xml方式与注解方式管理事务小结:
今日总结:
以后直接使用即可。
1. 注解AOP编程:
1. 确定目标类bean
2. 确定增强(通知)类,bean
3. 使用@Aspect定义切面,使用@Pointcut定义切入点。
在对应的增强方法上使用@Before,@Around等完成切入点与通知的关联
applicationContext.xml中:
这里如果想使用cglib的代理,还可以在 内设置proxy-target-class="true"
2. JdbcTemplate
为简化数据库操作,Spring提供了JdbcTemplate模板类,为了简化JdbcTemplate的开发,Spring提供了JdbcDaoSupport。
Dao层继承该类,传入对应数据源就可以直接获取对应的Template操作数据库。
JdbcTemplate/HibernateTemplate...
---------------------------------------------------------------------------
1. db.properties外部配置文件
jdbc.dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
2. 在applicationContext.xml中读取抽取出去的变量
首先要使用context:property-placeholder标签引入外界配置文件。
1. 因此首先要导入,context有关的schema约束。
2. 引入外界配置文件设置
3. 引入变量
............................
3. 声明式事务管理
两种方式:
-
XML
配置进行事务管理 - 注解配置事务管理
注解配置进行事务管理:
1. 将目标类定义成bean即可.增强类我们不需自己实现。
2. 在需要进行事务管理的方法/类上使用@Transactional(这里可以配置事务策略)
3. 配置注解事务管理器
applicationContext.xml配置注解驱动事务管理器:
XML
配置事务管理:【推荐】
1. 确定目标类,注册bean
2. 确定增强类,注册bean(Spring已经实现,只需注册该则增强类即可)
3. 配置事务管理器(Spring实现的增强类需要注入事务管理器)
4. 配置切面(切入点与通知的关联)
外部配置文件db.properties:
jdbc.dataSourceClass=com.mchange.v2.c3p0.ComboPooledDataSource
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
applicationContext.xml配置文件最终版: