Spring学习05-[AOP学习-AOP原理和事务]

AOP原理和事务

  • AOP
    • AOP底层原理
      • 比如下面的代码案例手动模拟AOP
    • 动态代理详解
      • JDK动态代理
        • 具体实现
      • Cglib动态代理
        • 具体实现
      • jdk动态代理和cglib动态代理的区别
  • 事务

AOP

AOP底层原理

在这里插入图片描述

当实现了AOP,Spring会根据当前的bean创建动态代理(运行时生成一个代理类)
面试题:为什么执行方法的时候,会执行切面里的通知方法?

比如下面的代码案例手动模拟AOP

  • 模拟切面类
@Component
public class LogAspect {
    public void logBefore() {
        System.out.println("aop前置通知");
    }

    public void logAfter(){
        System.out.println("aop后置通知");
    }

    public void logReturn(){
        System.out.println("aop返回通知");
    }

    public void logThrowting(){
        System.out.println("aop异常通知");
    }

}

  • 动态代理类
@Component
public class ProxyUserService extends UserService {

    @Autowired
    private LogAspect logAspect;

    @Override
    public String add() throws InterruptedException {
        String result = null;
        try {
            //调用切面类-前置通知
            logAspect.logBefore();

            //调用目标方法
            result = super.add();

            //调用切面类返回通知
            logAspect.logReturn();

        } catch (Exception e) {
            //调用切面类-异常通知
            logAspect.logThrowting();
            e.printStackTrace();
        } finally {
            //调用切面类-后置通知
            logAspect.logAfter();
        }

        return result;
    }
}

在这里插入图片描述
为什么断点可以进入切面类中的通知方法中?
从上述代码中可以看到,在AOP动态代理中,在Spring代理类中,帮我们调用了切面中的前置通知,后置通知、返回通知、异常通知这些通知方法,所以断点可以进入。

动态代理详解

  • jdk动态代理
  • cglib动态代理

JDK动态代理

JDK动态代理是基于接口的,生成出来的代理类实现了类接口

  • 核心代码

第一个参数:类加载器
第二个参数:需要代理的接口
第三个参数:InvocationHandler(调用程序处理器,必须重写invoke方法)

Proxy.newProxyInstance(TestJdkProxy.class.getClassLoader(),
                UserService.class.getInterfaces(),
                new MyHandler(new UserService())
        );
具体实现
  • 接口
public interface IUserService {
    void add();
}
  • 实现类
public class UserService implements IUserService{

    @Override
    public void add() {
        System.out.println("添加用户");
    }
}

  • 自定义一个InvocationHandler(目的是优化代码降低耦合,提高代码维护性)
public class MyHandler implements InvocationHandler {

    Object target;

    public MyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行前置通知");

        //执行目标方法
        Object returnValue = method.invoke(target, args);

        System.out.println("执行后置通知");

        return returnValue;
    }
}
  • 测试
    生成出来的代理类instance 实现了IUserService 接口
@Component
public class TestJdkProxy{

    public void test(){
        IUserService instance = (IUserService) Proxy.newProxyInstance(TestJdkProxy.class.getClassLoader(),
                UserService.class.getInterfaces(),
                new MyHandler(new UserService())
        );
        //生成出来的代理类instance 实现了IUserService 接口
        instance.add();
    }
}

在这里插入图片描述

Cglib动态代理

用JDK动态代理实现有一个缺点,必须实现接口,Cglib就回避了这个问题,因为cglib实现机制是基于子父类的

cglib动态代理不同于jdk动态代理。cglib动态代理需要依赖于第三方jar包,但是被spring进行了整合,所以不用特意的去引jar包

  • 核心代码
 Enhancer enhancer = new Enhancer();

        //设置被代理的类
        enhancer.setSuperclass(PersonService.class);

        //设置处理类
        enhancer.setCallback(new MyCallback(new PersonService()));

        //生成基于cglib动态代理的 代理类,不同于jdk动态代理它是继承自PersonService
        PersonService personService = (PersonService) enhancer.create();
        personService.add();
具体实现
  • 需要代理的类
public class PersonService {
    public void add(){
        System.out.println("添加人口");
    }
}
  • 自定义mycallback,需要实现MethodInterceptor接口
public class MyCallback implements MethodInterceptor {

    Object object;

    public MyCallback(Object object) {
        this.object = object;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行前置通知");

        //执行目标方法
        Object returnValue = method.invoke(object, args);

        System.out.println("执行后置通知");

        return returnValue;
    }
}
  • 测试
    生成基于cglib动态代理的 代理类,不同于jdk动态代理它是继承自PersonService
   public void test(){
        Enhancer enhancer = new Enhancer();

        //设置被代理的类
        enhancer.setSuperclass(PersonService.class);

        //设置处理类
        enhancer.setCallback(new MyCallback(new PersonService()));

        //生成基于cglib动态代理的 代理类,不同于jdk动态代理它是继承自PersonService
        PersonService personService = (PersonService) enhancer.create();
        personService.add();
    }

jdk动态代理和cglib动态代理的区别

jdk动态代理是基于接口的,只能代理实现了接口的类。cglib动态代理基于继承的,可以代理未实现接口的类

  • jdk动态代理会生成一个实现了接口的代理类
  • cglib动态代理会继承一个目标类的代理类
    在这里插入图片描述

事务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/783580.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA之(static关键字、final关键字)

JAVA之(static关键字、final关键字) 一、 static关键字1、静态变量2、静态方法3、 静态代码块4、例子 二、final关键字1、final修饰类2、 final修饰方法3、修饰变量 一、 static关键字 1、静态变量 private static String str1“staticProperty”2、静…

适合中小企业的MES管理系统有哪些特点

在当今竞争激烈的商业环境中,中小企业对于高效、灵活的生产管理系统的需求日益凸显。面对这些企业的MES管理系统不仅成为监控生产过程的得力助手,还通过提供关键数据,构建起客户期望与制造车间实时订单状态之间的紧密桥梁,以下是对…

Vue3使用markdown编辑器之Bytemd

官网地址:https://bytemd.js.org/playground GitHub地址:https://github.com/bytedance/bytemd ByteMD 是字节跳动出品的富文本编辑器,功能强大,可以免费使用,而且支持很多掘金内置的主题,写作体验很棒。 …

【Unity2D 2022:Particle System】添加拾取粒子特效

一、创建粒子特效游戏物体 二、修改粒子系统属性 1. 基础属性 (1)修改发射粒子持续时间(Duration)为3s (2)取消勾选循环(Looping) (2)修改粒子存在时间&…

星网安全产品线成立 引领卫星互联网解决方案创新

2024年6月12日,盛邦安全(688651)成立星网安全产品线,这是公司宣布全面进入以场景化安全、网络空间地图和卫星互联网安全三大核心能力驱动的战略2.0时代业务落地的重要举措。 卫星互联网技术的快速发展,正将其塑造为全球…

leetcode:编程基础0到1

文章目录 交替合并字符串str.length();StringBuilder类型 ,toString()append() ,chatAt()题目描述 交替合并字符串 str.length(); 输出字符串str的长度 StringBuilder类型 ,toString() append() ,chatAt() 题目描述 class Solution {public String …

(译文)IRIG-B对时编码快速入门

原文 PDF:https://ww1.microchip.com/downloads/aemDocuments/documents/FTD/tekron/tekronwhitepapers/221223-A-guide-to-IRIG-B.pdf IRIG-B3 概论 Inter-Range Instrument Group 时间码(简称IRIG)是一系列标准时间码格式。用于将时间信…

俄罗斯VK Ads开户充值全流程!VK如何开户?VK如何注册?VK广告

在俄罗斯,VK(VKontakte)是一个广受欢迎的社交媒体平台,对于寻求进入该市场的企业来说,进行VK广告推广是一条有效途径。 首先,你需要明确自己要推广的产品或服务,并且确定目标市场和受众。 由于…

1.8.0-矩阵乘法的反向传播-简单推导

1相关资料 之前分享过一个博客里面写的,我们大致了解并记住结论的博客:【深度学习】7-矩阵乘法运算的反向传播求梯度_矩阵梯度公式-CSDN博客;这里再分享一下自然语言处理书上关于这部分的推导过程:3-矩阵相乘-梯度反向传播的计算…

如何下载jmeter旧版本

如何下载jmeter旧版本 推荐先用旧版本做好测试基本操作,因为高版本不适合做压力测试,需要证书,有点麻烦。 1.百度或直接打开jmeter官网:https://jmeter.apache.org/ 2.向下拖到Archives一栏,点击Apache Jmeter archi…

ICC2:ignore pin的设置

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 相关文章链接:

OS Copilot测评

1.按照第一步管理重置密码时报错了,搞不懂为啥?本来应该跳转到给的那个实例的,我的没跳过去 2.下一步重置密码的很丝滑没问题 3安全组新增入库22没问题 很方便清晰 4.AccessKey 还能进行预警提示 5.远程连接,网速还是很快,一点没卡,下载很棒 6.替换的时候我没有替换<>括…

六、快速启动框架:SpringBoot3实战-个人版

六、快速启动框架&#xff1a;SpringBoot3实战 文章目录 六、快速启动框架&#xff1a;SpringBoot3实战一、SpringBoot3介绍1.1 SpringBoot3简介1.2 系统要求1.3 快速入门1.4 入门总结回顾复习 二、SpringBoot3配置文件2.1 统一配置管理概述2.2 属性配置文件使用2.3 YAML配置文…

调制信号识别系列 (一):基准模型

调制信号识别系列 (一)&#xff1a;基准模型 说明&#xff1a;本文包含对CNN和CNNLSTM基准模型的复现&#xff0c;模型架构参考下述两篇文章 文章目录 调制信号识别系列 (一)&#xff1a;基准模型一、论文1、DL-PR: Generalized automatic modulation classification method b…

如何优化 PostgreSQL 中对于复杂数学计算的查询?

文章目录 一、理解复杂数学计算的特点二、优化原则&#xff08;一&#xff09;索引优化&#xff08;二&#xff09;查询重写&#xff08;三&#xff09;数据库配置调整&#xff08;四&#xff09;使用数据库内置函数的优势 三、具体的优化方案和示例&#xff08;一&#xff09;…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【加密导入密钥(C/C++)】

加密导入密钥(C/C) 以加密导入ECDH密钥对为例&#xff0c;涉及业务侧加密密钥的[密钥生成]、[协商]等操作不在本示例中体现。 具体的场景介绍及支持的算法规格。 在CMake脚本中链接相关动态库 target_link_libraries(entry PUBLIC libhuks_ndk.z.so)开发步骤 设备A&#xf…

【机器学习】——决策树模型

&#x1f4bb;博主现有专栏&#xff1a; C51单片机&#xff08;STC89C516&#xff09;&#xff0c;c语言&#xff0c;c&#xff0c;离散数学&#xff0c;算法设计与分析&#xff0c;数据结构&#xff0c;Python&#xff0c;Java基础&#xff0c;MySQL&#xff0c;linux&#xf…

PHP宝藏神器多功能投票系统源码小程序

&#x1f389;发现宝藏神器&#xff01;一键解锁“多功能投票小程序”的无限可能✨ &#x1f308; 开篇安利&#xff1a;告别繁琐&#xff0c;拥抱高效&#xff01; Hey小伙伴们&#xff0c;是不是经常为组织活动、收集意见而头疼不已&#xff1f;&#x1f92f; 今天就要给大…

迭代器模式(大话设计模式)C/C++版本

迭代器模式 C #include <iostream> #include <string> #include <vector>using namespace std;// 迭代抽象类,用于定义得到开始对象、得到下一个对象、判断是否到结尾、当前对象等抽象方法&#xff0c;统一接口 class Iterator { public:Iterator(){};virtu…

Android约束布局的概念与属性(2)

目录 3&#xff0e;链式约束4&#xff0e;辅助线 3&#xff0e;链式约束 如果两个或以上控件通过下图的方式约束在一起&#xff0c;就可以认为是他们是一条链&#xff08;如图5为横向的链&#xff0c;纵向同理&#xff09;。 图5 链示意图 如图5所示&#xff0c;在预览图中选…