Spring-动态代理深入了解

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring-动态代理深入了解

😀前言

本篇的Spring-AOP系类文章第二篇扩展了Spring-动态代理然后开发了简易的AOP类

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉


🥰Spring-动态代理深入了解

😁代码演示–动态代理深入

需求说明

  1. 有一个 SmartAnimal 接口,可以完成简单的加减法, 要求在执行 getSum()和 getSub() 时,输出执行前,执行过程,执行后的日志输出

💖输出结果

日志-方法名-getSum-参数 10.0 2.0

方法内部打印 result = 12.0

日志-方法名-getSum-结果 result= 12.0


日志-方法名-getSub-参数 10.0 2.0

方法内部打印 result = 8.0

日志-方法名-getSub-结果 result= 8

创建步骤

  1. 创建接口 SmartAnimalable.java
public interface SmartAnimalable {
    //求和
    float getSum(float i, float j);
    //求差
    float getSub(float i, float j);
}
  1. 实现类SmartDog
public class SmartDog implements SmartAnimalable {
    @Override
    public float getSum(float i, float j) {
        //System.out.println("日志-方法名-getSum-参数 " + i + " " + j);
        float result = i + j;
        System.out.println("方法内部打印result = " + result);
        //System.out.println("日志-方法名-getSum-结果result= " + result);
        return result;
    }
    @Override
    public float getSub(float i, float j) {
        //System.out.println("日志-方法名-getSub-参数 " + i + " " + j);
        float result = i - j;
        System.out.println("方法内部打印result = " + result);
        //System.out.println("日志-方法名-getSub-结果result= " + result);
        return result;
    }
}
  1. 创建MyProxyProvider类

注意这里就没有使用上面直接new一个对象来调用了而是直接使用反射

这里也考虑了出现异常的问题

执行思路

定义我们要执行的目标对象, 该对象需要实现SmartAnimalable

构造器

方法, 可以返回代理对象,该代理对象可以执行目标对象

  • 先到的类加载器/对象
  • 得到要执行的目标对象的接口信息
  • 创建InvocationHandler

最后 创建代理对象并返回

public class MyProxyProvider {
    //定义我们要执行的目标对象, 该对象需要实现SmartAnimalable
    private SmartAnimalable target_obj;
    //构造器
    public MyProxyProvider(SmartAnimalable target_obj) {
        this.target_obj = target_obj;
    }
    //方法, 可以返回代理对象,该代理对象可以执行目标对象
    public SmartAnimalable getProxy() {
        //1. 先到的类加载器/对象
        ClassLoader classLoader = target_obj.getClass().getClassLoader();
        //2. 得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_obj.getClass().getInterfaces();
        //3. 创建InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    System.out.println("方法执行前-日志-方法名-" + method.getName() + "-参数 "
                            + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
                    //使用反射调用方法
                    result = method.invoke(target_obj, args);
                    System.out.println("方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
                            + result);//从AOP看, 也是一个横切关注点-返回通知
                } catch (Exception e) {
                    e.printStackTrace();
                    //如果反射执行方法时,出现异常,就会进入到catch{}
                    System.out.println("方法执行异常-日志-方法名-" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
                } finally {//不管你是否出现异常,最终都会执行到finally{}
                    //从AOP的角度看, 也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }
                return result;
            }
        };
        //创建代理对象
        SmartAnimalable proxy =
                (SmartAnimalable)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}
创建测试类
@Test
    public void smartDogTestByProxy() {
        SmartAnimalable smartAnimalable = new SmartDog();
        MyProxyProvider myProxyProvider =
                new MyProxyProvider(smartAnimalable);
        //我们返回了代理对象
        SmartAnimalable proxy =
                myProxyProvider.getProxy();
        proxy.getSum(10, 2);
        System.out.println("====================");
        proxy.getSub(10, 2);
    }

💞 ● 问题提出

  1. 在 MyProxyProvider.java 中, 我们的输出语句功能比较弱,在实际开发中,我们希望是 以一个方法的形式,嵌入到真正执行的目标方法前

使用土方法解决前面的问题

把输出语句抽出来在上面形成一个方法

创建步骤

  1. 创建MyProxyProvider
//我们一个方法,在目标对象执行前执行
    public void before(Object proxy, Method method, Object[] args) {
       System.out.println("before-方法执行前-日志-方法名-" + method.getName() + "-参数 "
               + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
    }
    //我们一个方法,在目标对象执行后执行
    public void after(Method method, Object result) {
       System.out.println("after-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
               + result);//从AOP看, 也是一个横切关注点-返回通知
    }
public SmartAnimalable getProxy() {
        //1. 先到的类加载器/对象
        ClassLoader classLoader = target_obj.getClass().getClassLoader();
        //2. 得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_obj.getClass().getInterfaces();
        //3. 创建InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    before(proxy, method, args);
                    //使用反射调用方法
                    result = method.invoke(target_obj, args);
                    after(method, result);
                } catch (Exception e) {
                    e.printStackTrace();
                    //如果反射执行方法时,出现异常,就会进入到catch{}
                    System.out.println("方法执行异常-日志-方法名-" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
                } finally {//不管你是否出现异常,最终都会执行到finally{}
                    //从AOP的角度看, 也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }
                return result;
            }
        };
        //创建代理对象
        SmartAnimalable proxy =
                (SmartAnimalable) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}

该方法问题分析:

耦合度高

❤️‍🔥对土方法解耦-开发简易的 AOP 类

创建步骤

  1. 创建WyxAOP.java
/**
 * 自己编写一个一个极简的AOP类
 */
public class WyxAOP {
    //我们一个方法,在目标对象执行前执行
    public static void before(Object proxy, Method method, Object[] args) {
        System.out.println("WyxAOP-方法执行前-日志-方法名-" + method.getName() + "-参数 "
                + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
    }
    //我们一个方法,在目标对象执行后执行
    public static void after(Method method, Object result) {
        System.out.println("WyxAOP-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
                + result);//从AOP看, 也是一个横切关注点-返回通知
    }
}
  1. 修改MyProxyProvider
public SmartAnimalable getProxy() {
        //1. 先到的类加载器/对象
        ClassLoader classLoader = target_obj.getClass().getClassLoader();
        //2. 得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_obj.getClass().getInterfaces();
        //3. 创建InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    WyxAOP.before(proxy, method, args);
                    //使用反射调用方法
                    result = method.invoke(target_obj, args);
                   WyxAOP.after(method, result);
                } catch (Exception e) {
                    e.printStackTrace();
                    //如果反射执行方法时,出现异常,就会进入到catch{}
                    System.out.println("方法执行异常-日志-方法名-" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
                } finally {//不管你是否出现异常,最终都会执行到finally{}
                    //从AOP的角度看, 也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }
                return result;
            }
        };
        //创建代理对象
        SmartAnimalable proxy =
                (SmartAnimalable) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}
完成测试
@Test
    public void smartDogTestByProxy() {
        SmartAnimalable smartAnimalable = new SmartDog();
        MyProxyProvider myProxyProvider =
                new MyProxyProvider(smartAnimalable);
        //我们返回了代理对象
        SmartAnimalable proxy =
                myProxyProvider.getProxy();
        proxy.getSum(10, 2);
        System.out.println("====================");
        proxy.getSub(10, 2);
    }

😄总结

本篇总结了Spring-动态代理然后开发了简易的AOP类使更容易理解

😍Spring-AOP系类文章

第一篇-> Spring-AOP的基本介绍以及通过先动态代理方式实现

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
7月前
|
监控 Java 开发者
Spring AOP动态代理
Spring AOP动态代理
103 1
|
7月前
|
运维 Java 程序员
Spring5深入浅出篇:Spring动态代理详解
# Spring动态代理详解 本文探讨了Spring中的MethodBeforeAdvice和MethodInterceptor在动态代理中的应用和差异。MethodBeforeAdvice在方法执行前执行额外功能,而MethodInterceptor则可在方法执行前后或抛出异常时运行额外逻辑。MethodInterceptor还能影响原始方法的返回值。
|
4月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
2月前
|
Java 数据安全/隐私保护 Spring
Spring进阶:初识动态代理
本文介绍了Spring框架中AOP切面编程的基础——动态代理。通过定义Vehicle接口及其实现类Car和Ship,展示了如何使用动态代理在不修改原代码的基础上增强功能。文章详细解释了动态代理的工作原理,包括通过`Proxy.newProxyInstance()`方法创建代理对象,以及`InvocationHandler`接口中的`invoke()`方法如何处理代理对象的方法调用。最后,通过一个测试类`TestVehicle`演示了动态代理的具体应用。
|
3月前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
6月前
|
XML Java 数据格式
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
53 0
|
7月前
|
监控 Java 数据库连接
Spring高手之路17——动态代理的艺术与实践
本文深入分析了JDK和CGLIB两种动态代理技术在Spring框架中的应用。讨论了动态代理的基础概念,通过实例展示了如何实现和应用这两种方法,并比较了它们的性能差异及适用场景。进一步,探讨了在动态代理中实现熔断限流和日志监控的策略,以及如何利用动态代理优化Spring应用的设计和功能。
124 6
Spring高手之路17——动态代理的艺术与实践
|
6月前
|
Java Spring
深入解析Spring源码,揭示JDK动态代理的工作原理。
深入解析Spring源码,揭示JDK动态代理的工作原理。
62 0
|
7月前
|
Java 数据库 Spring
切面编程的艺术:Spring动态代理解析与实战
切面编程的艺术:Spring动态代理解析与实战
64 0
切面编程的艺术:Spring动态代理解析与实战
|
7月前
|
设计模式 运维 Java
Spring5深入浅出篇:Spring中静态代理与动态代理
Spring框架中的代理模式分为静态代理和动态代理。在JavaEE分层开发中,Service层最为重要,包含核心业务逻辑和额外功能。静态代理通过手动创建代理类来增加原始类的额外功能,但当代理类数量多时管理不便且不易于维护。动态代理则解决了这一问题,通过Spring的AOP(面向切面编程)实现,无需手动创建代理类,只需定义切点和增强(额外功能),在运行时动态生成代理对象,提高了代码的灵活性和可维护性。动态代理主要利用了JVM的字节码技术,在运行过程中创建代理类,执行完毕后随着虚拟机的结束而销毁,不会产生持久化的代理类。