Spring-Spring之AOP底层原理解析---实践(动态代理)

动态代理

代理模式的解释:其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。

cglib动态代理 方式一:

public class UserService  {
 
 public void test() {
  System.out.println("test...");
 }
 
}
UserService target = new UserService();
 
// 通过cglib技术
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
 
// 定义额外逻辑,也就是代理逻辑
enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
 @Override
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  System.out.println("before...");
  Object result = methodProxy.invoke(target, objects);
  System.out.println("after...");
  return result;
 }
}});
 
// 动态代理所创建出来的UserService对象
UserService userService = (UserService) enhancer.create();
 
// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
userService.test();

执行结果:

cglib动态代理 方式二

声明两个不同的方法

public class UserService  {
 
 public void test() {
  System.out.println("test...");
 }

public void a() {
  System.out.println("aaaaa...");
 }

 
}

添加无任何逻辑的拦截器:NoOp.INSTANCE

然后执行不同的代理方法test() 和a()

public static void main(String[] args) {

        UserService target = new UserService();

        // 通过cglib技术
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);

        // 定义额外逻辑,也就是代理逻辑
        enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("before...");
//                Object result = methodProxy.invoke(target, objects);
//                Object result = methodProxy.invokeSuper(o, objects);
                Object result = method.invoke(target, objects);
                System.out.println("after...");
                return result;
            }
        }, NoOp.INSTANCE}); //NoOp.INSTANCE为无任何逻辑的拦截器

        enhancer.setCallbackFilter(new CallbackFilter() {
            @Override
            public int accept(Method method) {
                if(method.getName().equals("test")){
                    return 0; //该数字为上面数组拦截器的下标
                }else {
                    return 1;
                }
            }
        });

        // 动态代理所创建出来的UserService对象
        UserService userService = (UserService) enhancer.create();

        // 执行这个userService的test方法时,就会额外会执行一些其他逻辑
        userService.test();
        //userService.a();
    }

当代理执行  userService.test();时,结果:

当代理执行  userService.a();时,结果:

JDK动态代理:

基于接口的动态代理

public interface UserInterface {
 public void test();
}
 
public class UserService implements UserInterface {
 
 public void test() {
  System.out.println("test...");
 }
 
}
   public static void main(String[] args) {
        UserService target = new UserService();

        // UserInterface接口的代理对象
        Object proxy = Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before...");
                Object result = method.invoke(target, args);
                System.out.println("after...");
                return result;
            }
        });

        UserInterface userService = (UserInterface) proxy;
        userService.test();



    }

执行结果:

Spring中的动态代理:

ProxyFactory

public class UserService  {
 
 public void test() {
  System.out.println("test...中奖了");
 }

public void a() {
  System.out.println("aaaaa...");
 }

 
}
public static void main(String[] args) {  
    UserService target = new UserService();

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.setInterfaces(UserInterface.class);
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("before...买彩票");
                Object result = invocation.proceed();
                System.out.println("after...兑换成功");
                return result;
            }
        });

        UserInterface userService = (UserInterface) proxyFactory.getProxy();
        userService.test();




    }

执行结果:

 Advice的分类

Before Advice:方法之前执行
After returning advice:方法return后执行
After throwing advice:方法抛异常后执行
After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后
Around advice:这是功能最强大的Advice,可以自定义执行顺序

public class UserService  {
 
 public void test() {
  System.out.println("test...中奖了");
 }

public void a() {
  System.out.println("aaaaa...");
 }

 
}

 Before Advice:方法之前执行
After returning advice:方法return后执行

After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后
Around advice:这是功能最强大的Advice,可以自定义执行顺序

public class ZsjBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("中奖之前,先去买财票");
    }
}
public class ZsjAfterAdvice implements AfterReturningAdvice {


    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("中奖后去兑换财票,换钱");
    }
}
public static void main(String[] args) {  
    UserService target = new UserService();

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.setInterfaces(UserInterface.class);
      
        proxyFactory.addAdvice(new ZsjBeforeAdvice());
        proxyFactory.addAdvice(new ZsjAfterAdvice());


        UserInterface userService = (UserInterface) proxyFactory.getProxy();
        userService.test();




    }

执行结果:

After throwing advice:方法抛异常后执行

public static void main(String[] args) {  
    UserService target = new UserService();

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.setInterfaces(UserInterface.class);
      
        proxyFactory.addAdvice(new ZsjBeforeAdvice());
        proxyFactory.addAdvice(new ZsjAfterAdvice());
      proxyFactory.addAdvice(new ZsjThrowAdvice());

        UserInterface userService = (UserInterface) proxyFactory.getProxy();
         userService.a();




    }
public class ZsjThrowAdvice implements ThrowsAdvice {

    public void afterThrowing(Method method, Object[] objects, Object target,NullPointerException e){
        System.out.println("方法抛出异常后执行");
    }

}

执行结果:

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

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

相关文章

hadoop 大数据环境配置 配置jdk, hadoop环境变量 配置centos环境变量 hadoop(五)

1. 遗漏一步配置系统环境变量,下面是步骤,别忘输入更新系统环境命令 2. 将下载好得压缩包上传至服务器: /opt/module 解压缩文件存放地址 /opt/software 压缩包地址 3. 配置环境变量: 在/etc/profile.d 文件夹下创建shell文件 …

【Nginx】CentOS 安装Nignx

CentOS上安装Nginx: 1. 打开终端:使用SSH或者直接在服务器上打开终端。 2. 更新系统:运行以下命令以确保您的系统软件包列表是最新的: sudo yum update3. 安装Nginx:运行以下命令以安装Nginx: sudo yum…

性能测试 —— Jmeter分布式测试的注意事项和常见问题

Jmeter是一款开源的性能测试工具,使用Jmeter进行分布式测试时,也需要注意一些细节和问题,否则可能会影响测试结果的准确性和可靠性。 Jmeter分布式测试时需要特别注意的几个方面 1. 参数化文件的位置和内容 如果使用csv文件进行参数化&…

人工智能基础_机器学习030_ElasticNet弹性网络_弹性回归的使用---人工智能工作笔记0070

然后我们再来看elastic-net弹性网络,之所以叫弹性是因为,他融合了L1和L2正则,可以看到 他的公式 公式中有L1正则和L2正则两个都在这个公式中 可以看到弹性网络,在很多特征互相联系的时候,非常有用,比如, 相关性,如果数学好,那么物理也好,如果语文好,那么英语也好 这种联系 正…

[论文分享] Never Mind the Malware, Here’s the Stegomalware

Never Mind the Malware, Here’s the Stegomalware [IEEE Security & Privacy 2022] Luca Caviglione | National Research Council of Italy Wojciech Mazurczyk | Warsaw University of Technology and FernUniversitt in Hagen 近年来,隐写技术已逐渐被观…

处理本地DNS劫持,导致域名解析失败

回顾情形 在公司内网,有同事反馈appstoreconnect.apple.com网站需要通过代理才能正常访问。 向我这边询问,否修改过路由策略; 检测域名 通过域名ping检测网址,https://ping.chinaz.com/astrill.com,来ping域名apps…

「实用场景教程」如何用日程控件DHTMLX Scheduler制作酒店预订日历?(一)

dhtmlxScheduler是一个类似于Google日历的JavaScript日程安排控件,日历事件通过Ajax动态加载,支持通过拖放功能调整事件日期和时间,事件可以按天,周,月三个种视图显示。 DHTMLX Scheduler正式版下载 在本教程中&…

Git | Git的基本操作以及原理介绍

文章目录 基本操作创建git仓库配置name和email .git目录的结构git add & git commit.git目录结构的变化 git追踪管理的数据git的版本回退回退的原理回退的三种情况 版本库中文件的删除git分支管理分支的删除合并分支时的冲突分支的合并模式分支策略git stash不要在master分…

reactive和effect,依赖收集触发依赖

通过上一篇文章已经初始化项目,集成了ts和jest。本篇实现Vue3中响应式模块里的reactive方法。 前置知识要求 如果你熟练掌握Map, Set, Proxy, Reflect,可直接跳过这部分。 Map Map是一种用于存储键值对的集合,并且能够记住键的原始插入顺…

谈谈一个IT杂家的职业生涯规划,你的护城河被AI 攻破了么

文章大纲 没有顶会的从业者:成为深度学习老中医AIGC 还未能克服的难点:忽然的惊喜 -- 大模型的智能涌现未来还能做点什么,从计算机视觉的发展走向看T 字型人才与护城河成为更加熟练使用人工智能的人 参考文献与学习路径 我的职业生涯将近十年…

JVM实战-JVM之类加载时机

目录 JVM实战-JVM之类加载时机1 主动引用2 被动引用 JVM实战-JVM之类加载时机 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机…

第一篇 《随机点名答题系统》简介及设计流程图(类抽奖系统、在线答题系统、线上答题系统、在线点名系统、线上点名系统、在线考试系统、线上考试系统)

专栏目录 第一篇 《随机点名答题系统》简介及设计流程图(类抽奖系统、在线答题系统、线上答题系统、在线点名系统、线上点名系统、在线考试系统、线上考试系统)-CSDN博客 第二篇 《随机点名答题系统》——题库管理详解(类抽奖系统、在线答题…

【luckfox】0、开发环境搭建

前言 本章简单介绍如何搭建luckfox的开发环境。 一、抓取luckfox源码 需要提前准备好ubuntu环境。 git clone https://github.com/LuckfoxTECH/luckfox-pico.git二、编译 youkaiubuntu:/home/luckfox/luckfox-pico$ ./build.sh lunchyoukaiubuntu:/home/luckfox/luckfox-p…

SoftwareTest6 - 用 Selenium 怎么点点点

用 Selenium 来点点点 一 . 什么是自动化 ?1.1 自动化测试的分类接口自动化测试UI 自动化测试 (界面测试) 1.2 实现自动化测试的工具 : selenium环境部署驱动 二 . selenium 的使用2.1 一个简单的示例 : 让谷歌浏览器在百度首页搜索蔡徐坤准备工作编写代码 2.2 打开谷歌浏览器…

C++内存分区 代码区 全局区 栈区 堆区

一.内存四区 1.1 代码区: 存放函数体的二进制代码,由操作系统进行管理。1.2 全局区: 存放全局变量,静态变量以及常量。1.3 栈区: 由编译器自动分配释放,存放函数的参数值,局部变量等。1.4 堆…

JVM虚拟机:垃圾回收器之G1

本文重点 在前面的课程中我们介绍了六个垃圾回收器,分别是新生代的三个以及老年代的三个,本文我们将介绍一个垃圾回收器,它既可以用于新生代又可以用于老年代,这个垃圾回收器就是G1。 G1垃圾回收器的特点 G1是一种服务器端的并发收集垃圾回收器,应用在多处理器和大容量…

大文件分片上传、断点续传、秒传

小文件上传 后端&#xff1a;SpringBootJDK17 前端&#xff1a;JavaScriptsparkmd5.min.js 一、依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</ve…

python数据处理作业4:使用numpy数组对象,随机创建4*4的矩阵,并提取其对角元素

每日小语 真理诚然是一个崇高的字眼&#xff0c;然而更是一桩崇高的业绩。如果人的心灵与情感依然健康&#xff0c;则其心潮必将为之激荡不已。——黑格尔 难点&#xff1a;如何创建&#xff1f;取对角元素的函数是什么&#xff1f; gpt代码学习 import numpy as np# 随机创…

【数据结构】树与二叉树(十六):二叉树的基础操作:插入结点(算法Insert)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

【MySQL系列】 第四章 · 约束

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…