Spring对DAO层和Service层的加强

Spring对DAO的增强体现在Dao对数据库的操作上(通俗的讲就是使用一个jdbc的模板)
Spring对Service层的增强体现在对事务的管理上,通过aop的思想将事务很好的整合了

一.Spring的AOP的注解入门

(一) AOP对DAO的增强

1. 创建web项目,引入jar包

2. 创建相关的包和类

  • 创建包com.cdut.aop.demo1,创建接口:
public interface CustomerDao {

    public void save();
    public void update();
    public void find();
    public Integer delete();

}
  • 创建类CustomerDaoImpl.java
public class CustomerDaoImpl implements CustomerDao {

    @Override
    public void save() {
        System.out.println("这是一个=保存=客户的方法");
    }

    @Override
    public void update() {
        System.out.println("这是一个=更新=客户的方法");
    }

    @Override
    public void find() {
        System.out.println("这是一个=查找=客户的方法");
    }

    @Override
    public Integer delete() {
        System.out.println("这是一个=删除=客户的方法");
        return null;
    }

}

3. 编写切面类,并且完成配置

@Aspect
public class MyAspectAnno {

    //方式一:在自定义的切面类里面讲通知和切点绑定
    @Before("MyAspectAnno.pointcut1() || MyAspectAnno.pointcut2()")
    public void before(){
        System.out.println("this is 前置");
    }

    @Pointcut("execution(* com.cdut.spring.demon.CustomerDaoImpl.save(..))")
    private void pointcut1(){};

    @Pointcut("execution(* com.cdut.spring.demon.CustomerDaoImpl.update(..))")
    private void pointcut2(){};


    //方式二: 直接在通知上织入
    @After("execution(* com.cdut.spring.demon.CustomerDaoImpl.find(..)))")
    public void after(){
        System.out.println("这个是后置的增强");
    }
}

4. 创建核心配置文件,配置实现类

src创建applicationContext.xml

引入约束(模板)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    </beans>
     <!--开启自动代理  -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <!--配置目标类: 其实就是CustomerDaoImpl -->
    <bean id="customerDao" class="com.cdut.spring.demon.CustomerDaoImpl"> </bean>

    <!-- 配置切面类 -->
    <bean id="myAspectAnno" class="com.cdut.spring.demon.MyAspectAnno"></bean>
    </beans>

5.编写测试类

注意Spring和JUnit的整合

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demon {

    //注入一个CustomerDao对象
    @Resource(name="customerDao")
    private CustomerDao customerDao;

    @Test
    public void test01(){
        customerDao.find();
        customerDao.save();
        customerDao.update();
        customerDao.delete();
    }
}

6. 输出结果显示

这是一个=查找=客户的方法
这个是后置的增强
this is 前置
这是一个=保存=客户的方法
this is 前置
这是一个=更新=客户的方法
这是一个=删除=客户的方法

7.总结

  • 这个小案例是使用Spring的AOP思想对DAO的一种增强.

    • Spring的AOP思想就是代理模式的体现–横向编程
  • 流程分析:

    • 首先是编写基本的类,注意在编写切面类的是后需要将通知和切点进行绑定

    • 第一种方式:先将通知和一个自定义的切点的绑定, 再将自定义的切点和连接点进行绑定

    • 第二种方式:一步到位 直接在通知上面将连接点绑定 不用去自定义一个切点了

    • 然后在配置文件中开启自动代理. 将目标类切面类配置进去

    • 最后编写一个测试类进行测试

(二) Spring的AOP的注解通知

1 其他通知的使用

  • 前置通知、后置通知、环绕通知、异常通知、后置通知
@Aspect
public class MyAspectAnno {

    @Before("execution(* com.cdut.spring.demon.CustomerDaoImpl.save(..))")
    public void before(JoinPoint joinpoint){
        System.out.println("前置增强==========");
    }

    @AfterReturning(value="execution(* com.cdut.spring.demon.CustomerDaoImpl.delete(..))",returning="result")
    public void afterReturning(JoinPoint joinpoint,Object result){
        System.out.println("后置增强=========="+result);
    }

    @AfterThrowing(value="execution(* com.cdut.spring.demon.CustomerDaoImpl.find(..))",throwing="ex")
    public void afterThrowing(JoinPoint joinpoint,Throwable ex){
        System.out.println("异常抛出增强======"+ex.getMessage());
    }

    @After(value="execution(* com.cdut.spring.demon.CustomerDaoImpl.find(..))")
    public void after(JoinPoint joinpoint){
        System.out.println("最终通知========");
    }


    @Around(value="execution(* com.cdut.spring.demon.CustomerDaoImpl.update(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前增强========");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后增强========");
        return obj;
    }
}

二. Spring中的事务管理(对Service层的优化)

(一) Spring的JDBC的模板

  • Spring称为是EE开发一站式框架,有EE开发每层解决方案。Spring对持久层提供了JDBC 模板和ORM模板。

1. Spring的JDBC的模板入门

  • 创建工程、引入jar包
  • 创建数据库和表
    • 创建数据库:myspring
    • 创建表 account
    • id
    • name
    • price
  • 编写测试类
public class JDBCTemplateDemon1 {

    @Test
    public void test01(){
        //创建一个数据源
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///myspring");
        dataSource.setUsername("root");
        dataSource.setPassword("123");

        //在模板中注入数据源,就可以连接数据库
        JdbcTemplate template = new JdbcTemplate();
        template.setDataSource(dataSource);
        template.update("insert into account values(?,?,?)", null,"东野圭吾",10000d);

    }
}

2. 将连接池的信息交给Spring管理

  • 配置applicationContext.xml
    • 配置约束:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    </beans>
  • 配置连接池
 <!-- 配置Spring的内置连接池 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///myspring"/>
        <property name="username" value="root"/>
        <property name="password" value="123"/>
    </bean>
    <!-- 配置JDBC的模板 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
  • 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JDBCTemplateDemon2 {

    @Resource(name="jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Test
    public void test01(){
        jdbcTemplate.update("insert into account values(?,?,?)",null,"热巴",200000d);
    }
}

3. 配置DBCP连接池:

<!-- 配置DBCP连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///myspring"/>
        <property name="username" value="root"/>
        <property name="password" value="123"/>
    </bean>

4. 配置C3P0连接池:

<!-- 配置C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///myspring"/>
        <property name="user" value="root"/>
        <property name="password" value="123"/>
    </bean>

5. 信息保存到属性文件中

  • 将数据库的信息放到jdbc.properties中
  • 定义属性文件jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///myspring
jdbc.username=root
jdbc.password=123
  • 在配置文件中引入属性文件
    • 方案一:通过bean标签引入的
<!-- 引入外部属性文件的方式一 -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"/>
    </bean>

​ 方案二:通过context标签引入的(推荐)

扫描二维码关注公众号,回复: 1838663 查看本文章
<!-- 引入外部属性文件的方式二-->
    <context:property-placeholder location="classpath:jdbc.properties"/> 
  • 修改连接池的配置${},加载属性文件的名称
<!-- 配置连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JDBCTemplateDemon2 {

    @Resource(name="jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Test
    public void test01(){
        jdbcTemplate.update("insert into account values(?,?,?)",null,"Rita",20000d);
    }
}

6. JDBC模板完成CRUD的操作

  • 增删改的方法

update(String sql,Object… args);

  • 查询的方法

T queryForObject(String sql,Class<T> requiredType,Object… args);

T queryForObject(String sql,RowMapper<T> rowMapper,Object… args);

List<T> query(String sql,RowMapper<T>,Object… args);

  • 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JDBCTemplateDemo2 {

    @Resource(name="jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Test
    public void demo1(){
        jdbcTemplate.update("insert into account values (?,?,?)",null,"思想",10000d);
    }
    @Test
    public void demo2(){
        jdbcTemplate.update("update account set name = ? , money = ? where id = ?","傻瓜",20000d,5);
    }
    @Test
    public void demo3(){
        jdbcTemplate.update("delete from account where id = ?",5);
    }
    @Test
    public void demo4(){
        String name = jdbcTemplate.queryForObject("select name from account where id = ?", String.class, 1);
        System.out.println(name);
    }
    @Test
    public void demo5(){
        Long count = jdbcTemplate.queryForObject("select count(*) from account", Long.class);
        System.out.println(count);
    }
    @Test
    public void demo6(){
        Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new MyRowMapper(), 1);
        System.out.println(account);
    }
    @Test
    public void demo7(){
        List<Account> list = jdbcTemplate.query("select * from account", new MyRowMapper());
        for (Account account : list) {
            System.out.println(account);
        }
    }

    //重点
    class MyRowMapper implements RowMapper<Account>{

        @Override
        public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
            Account account = new Account();
            account.setId(rs.getInt("id"));
            account.setName(rs.getString("name"));
            account.setPrice(rs.getDouble("price"));
            return account;
        }
    }
}

7.总结

  • 关于JDBC的模板,就是建立一个数据源,将这个数据源注入到模板中就可以使用了
    • 将信息保存到一个配置文件中
    • 在xml中引入这个文件
    • 然后配置一个连接池
    • 再配置一个JDBC模板,将连接池注入
    • 注意一下接受参数时需要自己实现一个接口

(二) Spring的事务的管理

1 事务的回顾

  • 事务的概念
    • 事务是逻辑上一组操作,组成这组操作各个逻辑单元,要么一起成功,要么一起失败。
  • 事务的特性(ACID)
    • 原子性
    • 一致性
    • 隔离性
    • 持久性
  • 读问题
    • 脏读
    • 不可重复读
    • 幻读

脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。

不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新(update)数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。

幻读(幻读):一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。

  • 设置事务隔离级别
    • read uncommitted
    • read committed(oracle默认)
    • repeatable read(mysql默认)
    • Serializable
隔离级别 含义
READ_UNCOMMITED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

2. Spring的事务管理的API

  • PlatformTransactionManager :平台事务管理器,是Spring真正管理事务对象。

    • DataSourceTransactionManager :针对JDBC事务管理
    • HibernateTransactionManager :针对Hibernate事务管理
  • TransactionDefinition :事务定义

    • 事务隔离级别
隔离级别 含义
DEFAULT 使用后端数据库默认的隔离级别(spring中的的选择项)
READ_UNCOMMITED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。
  • 事务传播行为(往下看)
  • 事务是否只读
  • 事务超时信息

    • TransactionStatus :事务状态信息
  • 是否有保存点
  • 是否已经完成
  • 是否已经回滚

总结:

Spring框架进行事务的管理,首先使用TransactionDefinition对事务进行定义(选择操作数据库的方式)。通过PlatformTransactionManager(JDBC、HIbernate)根据TransactionDefinition(隔离级别、传播行为、是否只读、是否超时)的定义信息进行事务的管理。在事务管理过程中产生一系列的状态:保存到TransactionStatus(是否提交、是否回滚)中。

3. Spring的事务管理:传播行为

  • 传播行为用来解决哪些问题

    • 用来解决复杂的事务操作,没有,一个还是多个事务
  • 事务传播行为的取值:

  • PROPAGATION_REQUIRED 传播行为的默认值。如果A中有事务,使用A中的事务。如果A没有事务,新建事务。
    PROPAGATION_SUPPORTS 如果A中有事务,就使用A中的事务,如果A没有事务,就不使用事务。
    PROPAGATION_MANDATORY 如果A中有事务,就使用A中的事务,如果A没有事务,报错。
    PROPAGATION_REQUIREDS_NEW 如果A中有事务,将A中的事务挂起。创建一个新的事务。
    PROPAGATION_NOT_SUPPORED 如果A中有事务,将A中事务挂起。非事务运行。
    PROPAGATION_NEVER 如果A中有事务,就报错。
    PROPAGATION_NESTED 使用嵌套事务。在A执行完毕后设置一个保存点,如果B中执行没问题,就执行通过,如果有异常,允许使用者回滚到保存点或者是回滚到最初始状态。

4. Spring的事务管理分类

  • Spring的编程式事务管理 :手动编写代码实现事务管理
    • 在实际应用中很少使用,原因是要修改原来的代码,加入事务管理代码 (侵入性 )
  • Spring的声明式事务管理 :通过配置实现事务管理
    • XML的声明式事务管理
    • 注解的声明式事务管理
  • 开发中经常使用声明式事务管理(代码侵入性最小)--推荐使用!
  • 不需要修改业务层的代码,也不需要手动添加transactionManager.commit(),也不需要手动添加transactionManager.rollback(),更不需要使用try…catch…,这一切都被封装好了,我们只需要配置就可以了。

(三) 搭建转账环境

1. 创建项目,引入jar包,导入数据

需求:账号转账,Tom账号取出1000元,存放到Jack账号上

  • 第一步:创建表account
  • 第二步:插入测试数据:
  • 第三步:查看测试数据:

2 在xml中配置

   <bean id="customerDao" class="com.cdut.jdbc.dao.impl.CustomerDaoImpl"></bean>

   <bean id="customerService" class="com.cdut.jdbc.service.impl.CustomerServiceImpl"></bean>


    <!-- 配置JDBC的模板 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <context:property-placeholder location="jdbc.properties"/>

    <!-- 配置连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

3 编写和配置DAO

定义AccountDao.java

public class CustomerDaoImpl implements CustomerDao {

    @Resource(name="jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void outMoney(String outName, Double moneny) {
        jdbcTemplate.update("update account set price = price - ? where name = ?", moneny,outName);
    }

    @Override
    public void inMoney(String inName, Double moneny) {
        jdbcTemplate.update("update account set price = price + ? where name = ?",moneny,inName);
    }

}

4 编写和配置Service

public class CustomerServiceImpl implements CustomerService {

    @Resource(name="customerDao")
    private CustomerDao customerDao;

    public void setCustomerDao(CustomerDao customerDao) {
        this.customerDao = customerDao;
    }

    @Override
    public void deal(String inName, String outName, Double moneny) {

        customerDao.outMoney(outName, moneny);

        customerDao.inMoney(inName, moneny);
    }
}

5 编写测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class demon01 {

    @Resource(name="customerService")
    private CustomerService customerService;

    @Test
    public void test01(){

        customerService.deal("rose", "jake", 1000.0);
    }

    @Test
    public void test02(){
        customerService.deal("jake", "rose", 1000.0);
    }
}

!! Spring的编程式事务管理(了解)

1 配置事务管理器

Jdbc的操作,需要配置Jdbc的事务管理器

配置applicationContext-tx1.xml

    <!-- 配置事务管理器=============== -->
        <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"
        ref="dataSource"/>
    </bean>

2 配置事务管理模板

配置applicationContext-tx1.xml

<!-- 配置事务管理的模板 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager"
        ref="transactionManager"/>
    </bean>

3 在业务层注入事务管理模板

配置applicationContext-tx1.xml

<!-- 配置Service -->
    <bean id="accountService" class="com.cdut.tx.demo1.AccountServiceImpl">
        <property name=*"accountDao" ref="accountDao"/>
        <property name="transactionTemplate" ref="transactionTemplate"/>
    </bean>

4 改写业务层的代码

AccountServiceImpl.java

   @Override
    public void transfer(final String from, final String to, final Double money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                accountDao.outMoney(from, money);
                int d = 1/0;
                accountDao.inMoney(to, money);
            }
        }); 
    }

问题;代码具有侵入性,开发效率很慢。

!!!!! (一) Spring的声明式事务管理:XML方式(AOP思想)

1 引入aop的jar包

2 恢复转账环境

3 导入Dao和Service

4 配置数据源

<!-- 引入外部属性文件的方式二 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 配置C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

5 配置事务管理器

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

6 配置事务

<!-- 配置事务的增强 :规定事务管理的标准-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="find*" read-only="true"/>
            <!-- 配置具体的方法的事务属性
                isolation//事务的隔离级别,默认是按数据库的隔离级别来
                propagation//事务的传播行为,默认是同一个事务
                timeout="-1":事务的超时时间,默认值使用数据库的超时时间。-1表示不会超时,timeout超时时间如果设置为2秒,也就是说发生事务回滚后,2秒钟后对用户响应。
                read-only="false":事务是否只读,默认可读写。
                rollback-for:遇到哪些异常就回滚,其他的都不回滚
                no-rollback-for:遇到哪些异常不回滚,其他的都回滚。和上面互斥的
                测试:no-rollback-for="java.lang.ArithmeticException",遇到算数异常不回滚
             -->

            -->
            <tx:method name="deal" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

7 进行AOP的增强

<!-- 配置AOP -->
    <aop:config>
        <aop:pointcut expression="execution(* com.cdut.jdbc.CustomerServiceImpl.deal(..))" id="pointcut1"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
    </aop:config>

8 编写测试类

9 声明式事务的原理

通过aop思想生成了代理类, 通过代理类来增强了原来的类再执行代理类

10 总结

  • 大概流程

    • 想要在service层插入事务,根据aop的原理来讲,需要先在xml中创建一个通知集(事务管理器,也就是我理解的切面), 事务管理器创建好了就要配置事务(从事务管理器中取出一个具体的事务),然后在aop配置中将切点找到, 与拿出来的事务进行绑定.
  • 在xml需要编写的代码

    • 引入约束
    • 注册dao
    • 注册service
    • 引入jdbc配置文件
    • 配置c3p0连接池(数据源)
    • 注册jdbc的模板(在dao层执行数据库的操作)
    • 注册事务管理器
    • 配置事务
    • 进行aop的增强

!!!!! (二) Spring的声明式事务的管理:注解方式

1 恢复开发环境

2 导入Dao、Service

3 在xml中配置

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 开启事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

4. service层

public class CustomerServiceImpl implements CustomerService {

    @Resource(name="customerDao")
    private CustomerDao customerDao;

    public void setCustomerDao(CustomerDao customerDao) {
        this.customerDao = customerDao;
    }

    @Override
    @Transactional
    public void deal(String inName, String outName, Double moneny) {

        customerDao.outMoney(outName, moneny);

        customerDao.inMoney(inName, moneny);
    }
}

或者在类上加上一个@Transactional

5.总结

  • 相比xml的开发模式, 注解开发显得更加方便

    • 在xml中配置一个事务管理器

    • 开启事务注解

    • 在service层中的类上或者方法上配置一个@Transactional 在这个@Transactional中可以配置想要的事务的级别

猜你喜欢

转载自blog.csdn.net/lr19941226/article/details/80799642