Spring-Aop和声明式事务

 2023-01-27
原文作者:一条小白白啊 原文地址:https://juejin.cn/post/7031917346574843940

AOP介绍

    aop:Aspect Oriented Programming,面向切面编程。是通过预编译方式(aspectj)或者**运行期动态代理**(Spring)实现程序功能的统一维护的技术。
    AOP是OOP(面向对象编程)的技术延续,是软件开发中的一个热点,也是Spring中的一个重要内容。利用AOP可以实现对业务逻辑各个部分之间的隔离,从而使得业务逻辑各部分之间的耦合性降低,提高程序的可重用性,同时提高了开发效率。
  • aop的作用:在不修改源码的情况下,进行功能增强,通过动态代理实现的 *``` 优势:减少重复代码,提高开发效率,方便维护
 *  aop的底层实现:底层是通过动态代理实现的。在运行期间,通过代理技术动态生成代理对象,代理对象方法执行时进行功能的增强介入,再去调用目标的方法从而完成功能的增强
       1.常见的动态代理技术有:

1.  jdk的动态代理:基于接口实现的
2.  cglib的动态代理:基于子类实现的 Spring的aop采用了哪种代理方式
3.  如果目标对象有接口,就采用JDK动态代理技术
4.  如果目标对象没有接口就采用cglib技术

### AOP相关概念 ###
连接点:能够被增强的方法都是连接点
切入点:已经增强的连接点叫切入点
通知/增强:对目标对象增强的代码
切面:是切入点和切面的结合

### AOP开发前要明确的事项 ###

我们需要做的事情
编写核心业务(目标类的相关方法)
编写通知类,通知类有通知方法(Advice增强功能方法)
在配置文件中配置织入关系,完成完整的代码逻辑运行

Spring的AOP做的事情
生成动态代理的过程(把通知织入到切入点的过程),是由spring来实现的
    Spring会监控切入点方法的执行,一旦发现切入点方法执行,使用代理机制动态创建目标对象的代理对象,根据通知的类别,在代理对象的对应位置,将通知对应的功能织入完成完整代码的逻辑运行

### 基于xml的AOP ###
入门实现:

##### 1.导入aop的依赖 #####

![202301012100184741.png][]

##### 2.创建目标类和通知类 #####
    public interface UserService {
    void add();

    void update();
}
    public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("调用了UserServiceImpl的add方法~!");
        //int a = 1 / 0 ;
    }

    public void update() {
        System.out.println("调用了UserServiceImpl的update方法~!");
    }

通知类(增强类):
    public class MyAdvice {

    public void print(){
        System.out.println("打印日志~!");
    }

##### 3.写配置文件 #####

![202301012100199702.png][]

![202301012100207283.png][]

#### 通知类型的介绍 ####
    前置通知      <aop:before>          通知方法在切入点方法之前执行
    后置通知      <aop:after-rurining>  在切入点方法执行后,执行通知方法
    异常通知      <aop:after-throwing>  在切入点方法抛出异常时,执行通知方法
    最终通知      <aop:after>           无论切入点是否有异常,最终都会执行该方法
    环绕通知      <aop:around>          通知方法在切入点之前还有之后都会执行

切面表达式的抽取,如果我们对一个方法在不同位置进行增强时,切面表达式重复多余,所以我们可以进行抽取

![202301012100219094.png][]

### 基于注解的AOP ###

第一步:开启AOP自动代理和IOC扫描包
<context:component-scan base-package="com.albb"/>
<aop:aspectj-autoproxy/>

第二步:在增强类和目标类头上打上注解让spring为其创建对象

第三步:在增强类头上打上@Aspect注解,告诉spring我是增强类,是用来做增强的

第四步:在通知方法上打上@After(切面表达式)...注解告诉spring要增强在目标方法的哪个位置,要增强哪个方法
@Component
@Aspect
public class MyAdvice {

    @Before("execution(* com.itheima..*.*(..))")
    public void print(){
        System.out.println("打印日志~");
    }

### 纯注解的方式 ###
纯注解是依赖于核心配置类的,我们创建一个核心配置类
在他头上打上
        @configuration 表示这是一个核心配置类
        @ComponentScan("com.albb“)表示开启ioc扫描包
        @EnableAspectJAutoProxy 表示开启aop自动代理

### 基于XML的声明事务控制 ###
1.定义事务的管理员

![202301012100224065.png][]
2.定义事务规则

![202301012100231906.png][] 3.定义切面

![202301012100238927.png][]

### 注解的方式声明事务控制 ###
1.定义事务管理员
2.开启事务注解
<tx:annotation-driven transaction-manager="tm"/>
3.在要开启事务的类或者方法上添加@Transactional

### 纯注解的方式声明事务控制 ###
1.定义配置类
    添加@EnableTransactionManager,表示开启事务注解
2.使用@Bean在配置类中创建事务管理员
3.给要使用事务的类或者方法添加@Transactional注解


[202301012100184741.png]: http://image.skjava.com/article/common/2023/1/202301012100184741.png
[202301012100199702.png]: http://image.skjava.com/article/common/2023/1/202301012100199702.png
[202301012100207283.png]: http://image.skjava.com/article/common/2023/1/202301012100207283.png
[202301012100219094.png]: http://image.skjava.com/article/common/2023/1/202301012100219094.png
[202301012100224065.png]: http://image.skjava.com/article/common/2023/1/202301012100224065.png
[202301012100231906.png]: http://image.skjava.com/article/common/2023/1/202301012100231906.png
[202301012100238927.png]: http://image.skjava.com/article/common/2023/1/202301012100238927.png