Spring学习笔记7,基于AOP使用声明式事务控制

版权声明:本博客的所有内容,包括文字、图片,均为本人原创。转载请附上来源。 https://blog.csdn.net/weixin_37659242/article/details/80116947

什么是AOP

AOP是Spring提供的关键特性之一。AOP即面向切面编程,是OOP编程的有效补充。使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。从而避免了在业务逻辑的代码中混入很多的系统相关的逻辑——比如权限管理,事物管理,日志记录等等。这些系统性的编程工作都可以独立编码实现,然后通过AOP技术切入进系统即可。从而达到了 将不同的关注点分离出来的效果。

AOP原理

aop面向切面编程的原理就是代理:
1、静态代理
采用一些工具类对原来的类生成一个代理类,代理类以.class存在。
AspectJ实现的AOP,他是将切面代码直接编译到Java类文件中。

2、动态代理(重点,spring基于动态代理实现aop)
在运行中,通过反射生成类的代理对象,在代理对象中对原来的对象进行增强。

spring采用动态代理的技术包括:

1、基于接口生成代理对象
根据接口方法生成代理对象,对原来的代理对象进行增强
使用jdk提供反射实现

2、基于生成代理对象
根据类生成一个子类(代理对象),在代理对象(子类)中对父类进行增强。
使用CGLib实现

通过运行代理的测试代码了解通过代理对原来对象进行增强的过程

  • 4.2.1编写原始类
public interface CustomerServiceAop {
    public void insertCustomer(CstCustomer cstCustomer,CstCustomerDetail cstCustomerDetail) ;
}
  • 4.2.2编写代理对象生成代码(了解)
    代理对象要对上边的CustomerServiceAop进行增强!!

    由于CustomerServiceAop是一个接口,使用jdk提供根据接口生成代理对象.
    生成代理,测试跟踪:
    这里写图片描述基于jdk的代理(根据接口生成代理对象)

public class TransactionManagerHandler  implements InvocationHandler {
    //目标对象,原始对象CustomerServiceAop
    private Object target;
    //通过构造方法设置目标对象
    public TransactionManagerHandler(Object target){
        this.target = target;
    }

    //proxy生成的代理对象
    //method目标对象方法的引用
    //args目标对象方法调用的参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //在方法之前增强,开启事务
        System.out.println("开启事务...");
        //通过反射调用原始对象的方法
        Object obj = method.invoke(target, args);
        //在方法之后增强,提交事务
        System.out.println("提交事务...");
        return obj;
    }


}

如果实现aop,对原始对象生成一个代理对象,在代理对象中添加增强的代码:
1、编写原始类
2、编写增强类 ,包括增强的代码
3、确定目标对象
4、生成代理对象,执行增强类的增强代码,执行原始类中代码

了解jdk和cglib区别

jdk:基于接口生成代理对象

cglib:基于类生成代理对象

spring底层使用jdk和cglib,如果原始对象实现了一个接口,spring使用jdk,否则 使用cglib生成代理。

扫描二维码关注公众号,回复: 3139311 查看本文章
AOP联盟

AOP联盟出一套aop的标准。
aop联盟的jar包:这里写图片描述

aop术语:

Pointcut(切入点):确定在哪个方法上增强,一个类有多个切点

Advice(通知/增强):在切点上进行增强,包括:前置增强、后置增强、抛出异常增强

Target(目标对象):对目标对象进行增强,生成代理对象

Proxy(代理):对目标对象进行增强,生成代理对象
Weaving(织入):生成代理的时机(过程)
1、动态代理织入,在运行期为目标类生成代理对象
2、编译期织入
Aspect(切面): 包括切点和增强,面向哪个切点进行增强(编程)。

Aop编程入门

加入aop相关jar包
 AOP联盟aopalliance-1.0.jar
 Spring aop包 spring-aop-4.2.4.RELEASE.jar
 AspectJ 框架jar包  aspectjweaver-1.8.7.jar
 Spring 对AspectJ 整合jar包  spring-aspects-4.2.4.RELEASE.jar

这里写图片描述

AspectJ语法(切点语法)

通过语法配置切入点:
切入点:方法,哪个/此类哪个/些方法

表达式包括两部分:函数名和操作参数。
例子:execution(* cn.itcast.spring.service.impl..(..)) 匹配cn.itcast.spring.service.impl包下所有类的所有方法(任意形参),任意返回值。

execution函数名
* cn.itcast.spring.service.impl..(..)参数

掌握:
execution(* cn.itcast.spring.service.impl..(..)) 匹配cn.itcast.spring.service.impl包下所有类的所有方法(任意形参),任意返回值

within(cn.itcast.service..*) 匹配 cn.itcast.service包下所有类 (包括子包)所有方法。

增强

AspectJ支持的增强类型:
Before 前置增强/通知,相当于BeforeAdvice
AfterReturning 后置增强/通知,相当于AfterReturningAdvice
Around 环绕增强/通知,相当于MethodInterceptor
AfterThrowing抛出增强/通知,相当于ThrowAdvice
After 最终finally增强/通知,不管是否异常,该通知都会执行


public void save(){
    try{
    //前置增强
    调用目标对象方法执行
    //后置增强

    }catch(Exception ex){
        //抛出异常增强
    }finally{
        //最终finally增强
    }
}
小结

代理对象生成流程:
1、spring要对目标类进行管理(前提!!!)
在容器中配置目标类
2、编写增强类(增强代码)
3、切点,spring根据切点找到目标类中目标方法。
4、生成代理对象(spring自动完成)


spring声明式事务

分析:
通过编程方法实现事务控制
1、编写增强类,实现环绕增强(前置增强+后置增强)、抛出异常增强
使用spring提供三个事务控制对象,进行实现。

2、配置aop切面

声明式事务控制:
1、增强类由spring提供
2、aop的切面还需要程序员配置

dao


继承hibernamteTemplate

service编写

不再使用手动控制事务代码!!
这里写图片描述

service配置

这里写图片描述

事务管理器

在applicatoinContext-transaction.xml
这里写图片描述

配置增强(实现事务 管理)

加入约束:

<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">

完整声明式事务配置:

<!-- 配置事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">

    <!-- 依赖sessionFactory -->
    <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 增强,实现事务管理 
    指定事务管理器

    -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 事务定义信息 
        propagation:传播 行为 REQUIRED表示需要在事务中运行,如果没有事务则开启一个新事务
        name:匹配方法名,执行方法时设置事务定义信息 insert*以insert开头的所有方法,设置传播行为为REQUIRED
        rollback-for:配置异常类的类路径,当此方法抛出此类异常则回滚事务,默认RuntimeException
        -->
        <tx:attributes>
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>

        </tx:attributes>
    </tx:advice>

    <!-- 切面
    包括:切点和增强
     -->
    <aop:config>
        <!-- 使用aop:advisor配置切面,和 tx:advice配置使用实现事务控制
        advice-ref :指定引用增强
        -->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.itcast.crm.service.impl.*.*(..))"/>
    </aop:config>

注意:

这里写图片描述

了解配置jdk或cglib

在aop代理配置处,可以通过proxy-target-class控制使用的代理方式:
proxy-target-class=false 默认值,使用jdk代理

<!-- aop代理配置 -->
<aop:config proxy-target-class="false">

proxy-target-class=true 使用cglib代理

<!-- aop代理配置 -->
<aop:config proxy-target-class="true">

如果此类没有实现接口,只能使用cglib代理!!!

注解方式事务控制

1、在service方法上使用@Transactional标识此方法进行事务控制
2、在xml配置

<!-- 注解驱动事务管理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

3、在xml中去掉xml方式声明式事务中
事务增强配置和aop切面配置
这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_37659242/article/details/80116947