Spring框架(二)整合Junit4、AOP开发、AOP事务管理详解

Spring框架(二)

整合Junit4单元测试

传统测试代码,测试spring时每个测试方法中都需要创建spring容器,测试非常麻烦,整合了Junit测试之后,可以在测试类中自动帮我们创建spring容器.我们可以不用每次测试都创建容器了.提高书写代码的效率.

导包

  • spring-beans spring-context spring-core spring-expression com.springsource.org.apache.log4j com.springsource.org.apache.commons.logging
  • spring-aop
  • spring-test junit4

搭建spring框架

准备对象
创建Spring配置

新建applicationContext.xml,导入约束

整合junit4测试

//在测试方法运行前先自动创建容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定配置文件路径
@Contextcontfinguration("classpath:applicationContext.xml")
public class Demo{
//将待测对象注入us属性中,name属性填写BeanName
@Resource(name="userService")
private UserService us;

Spring中的AOP开发

AOP思想

AOP思想:面向切面编程
纵向重复,横向抽取.

spring中aop开发概念

spring封装了代理技术,通过代理技术来体现aop思想,我们使用代理体现aop时,不需要我们自己书写代理代码,spring帮我们完成.

spring中封装的代理技术

动态代理

局限性:生成代理类时,必须基于接口,生成的代理对象实际上就是接口的实现类.spring中的aop是希望能够对象所有对象生成代理的.基于该动态代理原则,会导致项目中很多类无法生成代理.

CGLib代理

spring为了能够对项目中所有类生成代理,所以引入了CGLib代理技术,该代理技术的特点是,对目标对象生成代理时,代理对象是被代理对象的子类.Hibernate应用了CGLib代理,懒加载技术中返回的就是cglib代理对象.

aop中的名称解释

aop联盟制定规范

  • 连接点 join point:目标对象中所有可以增强的方法.
  • 切点 point cut:已经或即将增加的方法.
  • 通知 advice:我们需要对目标方法增强的代码.
  • 目标对象 target:我们需要增强的对象
  • 代理对象 proxy:将通知应用到目标对象生成的对象
  • 织入 weaving:将通知织入到目标对象的过程.
  • 切面 aspect|advistor:切点+通知

springAOP开发步骤(xml)

导包
  • spring-beans spring-context spring-core spring-expression com.springsource.org.apache.log4j com.springsource.org.apache.commons.logging
  • spring-aop spring-aspect
  • aspect织入包 aop联盟规范包
  • spring-test junit4
准备目标对象
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        System.out.println("添加用户");
    }
    @Override
    public void delete() {
        System.out.println("删除用户");
    }
    @Override
    public void update() {
        System.out.println("修改用户");
    }
    @Override
    public void find() {
        System.out.println("查找用户");
    }
}   
准备通知对象

使用方法表达通知

  • 前置通知
  • 环绕通知
  • 后置通知-如果目标方法抛出异常,就不执行通知
  • 后置通知-无论目标方法是否抛出异常,都执行通知
  • 异常拦截通知

    @Before(“MyAdvice.myPC()”)
    public void before(){
    System.out.println(“我是前置通知”);
    }

    public Object around(ProceedingJoinPoint pjp) throws Throwable{
    System.out.println(“我是环绕通知前半部分”);
    Object proceed = pjp.proceed();
    System.out.println(“我是环绕通知后半部分”);
    return proceed;
    }

    public void afterReturning(){
    System.out.println(“我是后置通知-如果目标方法抛出异常,就不执行通知”);
    }

    public void after(){
    System.out.println(“我是后置通知-无论目标方法是否抛出异常,都会执行通知”);
    }

    public void afterThrowing(){
    System.out.println(“我是异常拦截通知”);
    }

配置生成代理对象

applicationContext.xml配置

  1. 注册目标对象
  2. 注册通知对象
  3. 配置切面(切点+通知)

    切点表达式语法
    public void cn.itcast.service.UserServiceImpl.save()
    void cn.itcast.service.UserServiceImpl.save() 修饰符任意
    * cn.itcast.service.UserServiceImpl.save() 返回值任意
    * cn.itcast.service.*ServiceImpl.save() 任何以ServiceImpl结尾的类
    * cn.itcast.service.*ServiceImpl.*() 任何方法
    * cn.itcast.service.*ServiceImpl.*(..) 任意参数   =>开发时使用的
    * cn.itcast.service..*ServiceImpl.*(..) 包含子孙包 => 开发时使用的
    
    配置切点
    id:为切点起个名字
    expression:填写切点表达式
    
    配置切面
    ref:指定通知对象
    
    前置通知切面
    method:通知方法
    pointcut-ref:qiedian
    










springAOP开发步骤(注解)

前面步骤相同
1. 注册目标对象
2. 注册通知对象
3. 开启使用注解配置aop

  • @Aspect 表示该类是通知类
  • @Before(“execution(表达式)”) 前置通知
  • @Around(“execution(表达式)”) 环绕通知
  • @AfterRunner(“execution(表达式)”) 后置通知
  • @After(“execution(表达式)”) 后置通知,不管是否抛异常,都执行
  • @AfterThrowing(“execution(表达式)”) 异常拦截通知

    //注册切点
    @Pointcut(“execution(* cn.itheima.service.impl.ServiceImpl.())”)
    public void myPC(){}

Spring中的aop事务

使用spring中的aop技术来管理事务

事务属性

事务隔离级别
  • 1 读未提交
  • 2 都已提交
  • 4 可重复读
  • 8 串行化
事务是否只读

true 只读
false 可修改

传播行为

当业务方法平行调用时,事务应如何管理.

PROPAGION_XXX :事务的传播行为

  • 保证同一个事务中
    PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
    PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
    PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常

  • 保证没有在同一个事务中
    PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
    PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
    PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
    PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行


springAOP事务管理(xml)

导包

  • spring-beans spring-context spring-core spring-expression com.springsource.org.apache.log4j com.springsource.org.apache.commons.logging
  • spring-aop spring-aspect
  • aspect织入包 aop联盟规范包
  • spring-test junit4
  • spring-jdbc spring-tx
  • 数据库驱动 c3p0连接池

创建Dao层对象

@Override   
public void increaseMoney(Integer id, Double money) {
    String sql = "update t_user set money=money+? where id=?";
    getJdbcTemplate().update(sql,money,id);
}

@Override
public void decreaseMoney(Integer id, Double money) {
    String sql = "update t_user set money=money-? where id=?";
    getJdbcTemplate().update(sql,money,id);
}

创建service层对象

public class BalanceServiceImpl implements BalanceService {
    private BalanceDao bd;

    public void transfer(Integer from, Integer to, double money) {

        bd.increaseMoney(to, money);

        bd.decreaseMoney(from, money);
    }

    public void setBd(BalanceDao bd){
        this.bd = bd;
    }
}

创建spring配置文件

连接池
<!-- 指定读取db.properties中的键值对 -->
<context:property-placeholder location="classpath:db.properties"/>

<!-- 连接池 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>
dao层配置
<!-- dao -->
<bean name="balanceDao" class="cn.it.dao.impl.BalanceDaoImpl">
    <property name="dataSource" ref="dataSource"></property>
</bean>
service层配置
<!-- service -->
<bean name="balanceService" class="cn.it.service.impl.BalanceServiceImpl">
    <property name="bd" ref="balanceDao"></property>
</bean>

AOP事务配置

事务核心事务管理器
<!-- 配置核心事务管理器 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>
配置事务通知&事务属性

引入tx约束

propagation:传播行为
read-only:是否只读
isolation:隔离级别

<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
        <tx:method name="delete*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
        <tx:method name="update*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
        <tx:method name="find*" propagation="REQUIRED" read-only="true" isolation="DEFAULT"/>
        <tx:method name="*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
    </tx:attributes>
</tx:advice>
配置切面完成织入
<!-- 配置织入 -->
<aop:config>
    <!-- 配置切点 -->
    <aop:pointcut expression="execution(* cn.itheima.service.impl.*ServiceImpl.*(..))" id="txPC"/>
    <!-- 配置切面 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPC"/>
</aop:config>

springAOP事务管理(注解)

  • 导包
  • 创建Dao层对象
  • 创建Service层对象
  • 创建Spring配置对象

与xml相同

AOP事务配置

事务核心事务管理器
<!-- 配置核心事务管理器 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>
开启使用注解配置事务
<tx:annotation-driven transaction-manager="transactionManager" />
使用注解管理事务
//类中的所有方法都应用aop事务
@Transactional(propagation=Propagation.REQUIRED,readOnly=true,isolation=Isolation.REPEATABLE_READ)
public class BalanceServiceImpl implements BalanceService {
    private BalanceDao bd;

    @Override
    @Transactional(propagation=Propagation.REQUIRED,readOnly=false,isolation=Isolation.REPEATABLE_READ)
    public void transfer(Integer from, Integer to, double money) {
        bd.increaseMoney(to, money);

        bd.decreaseMoney(from, money);
    }

    public void setBd(BalanceDao bd){
        this.bd = bd;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值