spring之AOP和声明式事务

发布时间:2022-08-19 11:30

1. AOP的基本概念

AOP(Aspect Oriented Programming),即面向切面编程。 (OOP:Object 面向对象编程)

比如去银行取款和查询余额

spring之AOP和声明式事务_第1张图片

有了AOP,你写代码时不需要把这个验证用户步骤写进去,即完全不考虑验证用户。只写取款和显示余额的业务代码。而在另一个地方,写好验证用户的代码。这个验证用户的代码就是切面代码,以后在执行取款和显示余额的时候,利用代理模式。将验证用户的功能在执行取款和显示余额前调用。

代码在Spring容器中执行的时候,通过配置告诉Spring你要把这段代码加到哪几个地方,Spring就会在执行正常业务流程的时候帮你把验证代码和取款代码织入到一起。

AOP真正目的是:你写代码的时候,只需考虑主流程,而不用考虑那些不重要的,但又必须要写的其它相同的代码,这些其它的相同代码所在的类就是切面类。

面向切面编程的核心就是代理模式。

AOP术语

JoinPoint(连接点):在程序执行过程中的某个阶段点,连接点就是指主业务方法的调用,它是客观存在的。

Pointcut(切入点):切入点指的是类或者方法名,满足某一规则的类或方法都是切入点,通过切入点表达式来制定规则。

Advice(通知):切入点处所要执行的程序代码,即切面类中要执行的公共方法。通知的类型有: 前置通知,后置通知,异常通知,最终通知,环绕通知。

Target(目标对象):被代理的对象。比如动态代理案例中的明星,房东。

Weaving(织入):织入指的是把新增的功能用于目标对象,创建代理对象的过程。

Proxy(代理):一个类被AOP织入增强后产生的结果类,即代理类。比如动态代理案例中的经纪人或中介

Aspect(切面):切面指的是切入点(规则)和通知(织入方法)的类 = 切入点+通知

Spring中代理方式的说明

  1. Spring在AOP编程中使用代理的方式

    1. 目标对象有接口:使用JDK代理

    2. 目标对象没有接口:使用CGLIB代理

  2. 在Spring的AOP编程中,代理对象则由Spring创建,不用自己写了。

  3. 我们要做的就是配置AOP

2. AOP编程:基于XML的配置

例子

当向数据库中保存账户的时候,使用日志记录下这次保存操作

面向切面编程的流程

  1. 开发业务类:添加账户

  2. 开发切面类:记录日志

  3. 使用AOP将业务类与切面类织入到一起,实现需求的功能

步骤

  1. AccountService业务接口有void save() 添加账户的方法

  2. AccountServiceImpl实现业务接口类,输出"保存账户"

  3. 创建LogAspect切面类,编写通知方法void printLog(),输出:"执行添加操作"

  4. 配置文件applicationContext.xml

操作

pom.xml

  1. 导入spring-context

  2. 导入开源的面向切面编程的组件: aspectjweaver

  3. 导入JUnit5



    4.0.0

    com.it
    AOP
    1.0-SNAPSHOT


    
        
        
            org.springframework
            spring-context
            5.2.0.RELEASE
        
        
        
            org.aspectj
            aspectjweaver
            1.8.13
        
        
        
            org.springframework
            spring-test
            5.2.0.RELEASE
            test
        
        
        
            org.junit.jupiter
            junit-jupiter
            5.5.2
            test
        
    

业务接口

package com.it.service;

/**
 * 账户业务接口
 */
public interface AccountService {

    /**
     * 保存账户
     */
    void save();
}

业务实现类

package com.it.service.impl;

import com.it.service.AccountService;

public class AccountServiceImpl implements AccountService {
    /**
     * 保存账户
     */
    @Override
    public void save() {
        System.out.println("保存账户");
    }
}

记录日志的工具类

package com.it.utils;

import java.sql.Timestamp;

/**
 * 记录日志功能的类:切面类 = 切入点(规则)+通知(方法)
 */
public class LogAspect {

    /**
     * 记录日志
     */
    public void printLog() {
        System.out.println(new Timestamp(System.currentTimeMillis()) + " 记录日志");
    }
}

执行流程分析

spring之AOP和声明式事务_第2张图片

 XML中关于AOP的配置

spring之AOP和声明式事务_第3张图片

applicationContext.xml配置文件

  1. 配置日志记录类,这是切面类:LogAspect

  2. 配置正常的业务类:AccountServiceImpl

  3. AOP配置 execution(public void com.it.service.impl.AccountServiceImpl.save())

注:在导入aop的命名空间,idea可以自动导入




    
    

    
    

    
    
        
        

        
        
            
            
        
    

测试类

/**
 * 测试类
 */
@ExtendWith(SpringExtension.class)  //指定第三方运行类
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAccount {

    @Autowired
    private AccountService accountService;

    @Test
    public void testSave() {
        System.out.println("业务对象类型:" + accountService.getClass());
        accountService.save();
    }

}

执行效果

业务对象类型:class com.sun.proxy.$Proxy17
2021-01-11 09:22:10.164 记录日志
保存账户

3. AspectJ表达式

作用

切入点表达式的作用:一组规则,指定哪些类和方法要被切入

切点函数

切入点函数 作用
execution 细粒度函数,精确到方法
within 粗粒度,只能精确到类
bean 粗粒度,精确到类,从容器中通过id获取对象

execution表达式语法

spring之AOP和声明式事务_第4张图片

?表示出现0次或1次

()  没有参数
(*) 1个或多个参数
(..) 0个或多个参数

.. 表示当前包和子包

4. AOP编程:常用标签和通知类型

AOP中的标签

spring之AOP和声明式事务_第5张图片

 

通知类型介绍

  • 前置通知:在主业务方法前执行

  • 后置通知:在主业务方法后执行

  • 异常通知:在主业务方法抛出异常的时候执行

  • 最终通知:无论主业务方法是否出现异常,都会执行。注:如果配置在后置通知的前面,会先执行最终通知

  • 环绕通知:相当于上面所有通知的组合

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号