Spring AOP及事务

93 阅读4分钟

什么是 Spring AOP ?

在介绍 Spring AOP 之前,⾸先要了解⼀下什么是 AOP?

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的 集中处理。⽐如⽤户登录权限的效验,没学 AOP 之前,我们所有需要判断⽤户登录的⻚⾯(中 的⽅法),都要各⾃实现或调⽤⽤户验证的⽅法,然⽽有了 AOP 之后,我们只需要在某⼀处配 置⼀下,所有需要判断⽤户登录⻚⾯(中的⽅法)就全部可以实现⽤户登录验证了,不再需要每 个⽅法中都写相同的⽤户登录验证了。

AOP 是⼀种思想,⽽ Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现,它们的关系和 IoC 与 DI 类似。

AOP 相关概念:

1. 切面(类)

切面是一个模块化单元,它封装了与横切关注点相关的行为。通俗来说就是某一方面的具体内容,比如用户的登录验证就是一个切面。

2.切点

切点是拦截规则,定义了在应用程序中哪些方法将被拦截并应用通知。

3. 通知

方法被拦截后具体要执行的动作。

image.png

4. 连接点

所有可能触发切点的点就是连接点,可以是方法调用、方法执行、异常处理等。

Spring AOP 的使用:

1. 添加依赖:

注意添加SpringBootAOP:

image.png

2.定义切面

image.png

3.切点

image.png

4.通知

image.png

5.连接点

image.png

运行结果:

image.png

未配置拦截规则类下方法的运行结果:

image.png

环绕通知:

image.png

拦截规则的语法(修饰符可以省略):

image.png

Spring AOP的实现原理:

image.png

image.png

两种实现方式:

1.JDK 动态代理:

要求:被代理类必须实现接口;

技术:反射

特点:创建时慢,运行时快。

2.CGLIB

被代理类可以不实现接⼝,是通过继承被代理类,在运⾏时动态的⽣成代理类对象。

特点:创建快,运行稍慢,可以代理所有的方法。

Spring Boot 统一功能处理

1. 用户登录权限校验

image.png

image.png

被拦截效果:

image.png

拦截器交互过程:

image.png

2.统一异常处理

通过这两个注解实现对异常的检测,返回自定义的类型数据。

image.png

第一个注解只能扫描含有controller注解的类,如果要扫描其他注解的类,可以通过 @ControllerAdvice(basePackages = "com.example.components")来标记要扫描的路径。

第二个注解标记了要处理的异常类型,具体的异常处理方法和返回值,方法名可以自行定义。

3.统一格式的数据返回

在业务代码将数据返回给前端时对数据进行加工后再返回给前端:

image.png

测试代码:

image.png

运行结果:

image.png

但是,上述统一返回结果存在问题,当返回数据为String时会报错,解决办法及引起错误原因如下:

错误类型:

image.png

原因及解决办法:

返回执行流程:
   1.方法返回的是String 
   2.统一数据返回之前处理->String Convert HashMap
   3.将HashMap_转换成application/ json字符串给前端(接口) 问题出在这一步

解决方法:
1.在返回数据之前,单独处理String类型
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     *  是否执行beforeBodyWrite 方法,返回true=执行
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }


    /**
     *  返回数据之前进行重写
     * @param body   原始数据
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if(body instanceof HashMap){
            return body;
        }
        HashMap<String,Object> result = new HashMap<>();
        result.put("code",200);
        result.put("msg","");
        result.put("data",body);
        if(body instanceof String){
            //当原始数据是字符串时需要单独处理,将其转换为json字符串
            try {
                return objectMapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}

2. 将StringHttpMessageConverter 去掉

@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
    }
}


Spring 事务

1. 编程式事务

image.png

image.png

运行结果:

image.png

2. 声明式事务

image.png

image.png

该注解的参数说明:

image.png

事务的隔离级别:

image.png

注意事项:当事务发生异常,并将可能发生异常的代码加上try_catch后,又可能导致事务无法正常回滚:

解决办法:

1.将异常抛出去,让框架感知到异常,如果框架感受到异常后,框架就会自动回滚事务。

image.png

2.手动回滚事务

image.png

image.png

transactional 原理:

image.png

3.事务的传播机制

事务的传播机制解决的是一个事务在多个方法中传递的问题:

image.png

事务的传播机制有哪些?

image.png

分类:

image.png

示例:

image.png

运行结果:

image.png

image.png

数据库中没有添加任何数据,说明进行了事务的回滚。