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

简介: Spring-AOP的基本介绍以及通过先动态代理方式实现

😀前言

本片文章是手动开发- 简单的 Spring 基于 XML 配置的程序

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


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

基本介绍

AOP 讲解: spring-framework-5.3.8/docs/reference/html/core.html#aop

AOP APIs : spring-framework-5.3.8/docs/reference/html/core.html#aop-api

动态代理-精致小案例

需求说明

1. 有 Vehicle(交通工具接口, 有一个 run 方法), 下面有两个实现类 Car 和 Ship

2. 当运行 Car 对象 的 run 方法和 Ship 对象的 run 方法时,输入如下内容, 注意观察前后有统一的输出.

定义一个接口类Vehicle

里面有一个方法run

public interface Vehicle {
public void run();
}
定义一个实现接口类的Car类
public class Car implements Vehicle {
    @Override
    public void run() {
        System.out.println("交通工具开始运行了...");
        System.out.println("小汽车在公路 running..");
        System.out.println("交通工具停止运行了...");
    }
}
定义一个实现接口类的Ship类
public class Ship implements Vehicle {
    @Override
    public void run() {
        System.out.println("交通工具开始运行了...");
        System.out.println("大轮船在水上 running..");
        System.out.println("交通工具停止运行了...");
    }
}
创建测试类Test.java

Vehicle vehicle = new Car();        //可以切换成 new Ship() vehicle.run();

来思考一下,

解决方案好吗? ===> 代码冗余, 其实就是单个对象的调用,并没有很好的解决

解决方案-动态代理方式-2

动态代理解决思路,在调用方法时,使用反射机制,根据方法去决定调用哪个对象方法

修改 Car类

public class Car implements Vehicle {
    @Override
    public void run() {
        System.out.println("小汽车在公路 running..");
    }
}

修改 Ship类

public class Ship implements Vehicle {
    @Override
    public void run() {
        System.out.println("大轮船在水上 running..");
    }
}

创建VehicleProxyProvider类

1.执行思路

2.定义一个属性

3.构造器

4.编写一个方法,可以返回一个代理对象, 该代理对象可以通过反射机制调用到被代理对象的方法

4.1 得到类加载器

4.2 得到要代理的对象/被执行对象 的接口信息,底层是通过接口来完成调用

4.3 创建InvocationHandler 对象

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * VehicleProxyProvider 该类可以返回一个代理对象.
 */
public class VehicleProxyProvider {
    //定义一个属性
    //target_vehicle 表示真正要执行的对象
    //该对象实现了Vehicle接口
    private Vehicle target_vehicle;
    //构造器
    public VehicleProxyProvider(Vehicle target_vehicle) {
        this.target_vehicle = target_vehicle;
    }
    //编写一个方法,可以返回一个代理对象, 该代理对象可以通过反射机制调用到被代理对象的方法
    //1. 这个方法非常重要, 理解有一定难度
    public Vehicle getProxy() {
        //得到类加载器
        ClassLoader classLoader =
                target_vehicle.getClass().getClassLoader();
        //得到要代理的对象/被执行对象 的接口信息,底层是通过接口来完成调用
        Class<?>[] interfaces = target_vehicle.getClass().getInterfaces();
        //创建InvocationHandler 对象
        //因为 InvocationHandler 是接口,所以我们可以通过匿名对象的方式来创建该对象
        /**
         *
         * public interface InvocationHandler {
         *  public Object invoke(Object proxy, Method method, Object[] args)
         *         throws Throwable;
         * }
         * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到
         *
         */
        InvocationHandler invocationHandler = new InvocationHandler() {
            /**
             * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到
             * @param o 表示代理对象
             * @param method 就是通过代理对象调用方法时,的哪个方法 代理对象.run()
             * @param args : 表示调用 代理对象.run(xx) 传入的参数
             * @return 表示 代理对象.run(xx) 执行后的结果.
             * @throws Throwable
             */
            @Override
            public Object invoke(Object o, Method method, Object[] args)
                    throws Throwable {
                System.out.println("交通工具开始运行了....");
                //这里是我们的反射基础 => OOP
                //method 是?: public abstract void com.hspedu.spring.proxy2.Vehicle.run()
                //target_vehicle 是? Ship对象
                //args 是null
                //这里通过反射+动态绑定机制,就会执行到被代理对象的方法
                //执行完毕就返回
                Object result = method.invoke(target_vehicle, args);
                System.out.println("交通工具停止运行了....");
                return result;
            }
        };
        /*
          public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
          1. Proxy.newProxyInstance() 可以返回一个代理对象
          2. ClassLoader loader: 类的加载器.
          3. Class<?>[] interfaces 就是将来要代理的对象的接口信息
          4. InvocationHandler h 调用处理器/对象 有一个非常重要的方法invoke
         */
        Vehicle proxy =
                (Vehicle)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}

解释说明

创建InvocationHandler 对象      

//因为 InvocationHandler 是接口,所以我们可以通过匿名对象的方式来创建该对象

       /**

        *

        * public interface InvocationHandler {

        *  public Object invoke(Object proxy, Method method, Object[] args)

        *         throws Throwable;

        * }

        * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到

        *

        */

解释public Object invoke(Object o, Method method, Object[] args)

* invoke 方法是将来执行我们的target_vehicle的方法时,会调用到

* @param o 表示代理对象

* @param method 就是通过代理对象调用方法时,的哪个方法 代理对象.run()

* @param args : 表示调用 代理对象.run(xx) 传入的参数

* @return 表示 代理对象.run(xx) 执行后的结果.

* @throws Throwable

解释ClassLoader loader,Class[] interfaces,InvocationHandler h

        public static Object newProxyInstance(ClassLoader loader,

                                         Class[] interfaces,

                                         InvocationHandler h)

         1. Proxy.newProxyInstance() 可以返回一个代理对象

         2. ClassLoader loader: 类的加载器.

         3. Class[] interfaces 就是将来要代理的对象的接口信息

         4. InvocationHandler h 调用处理器/对象 有一个非常重要的方法invoke

创建Test.java 类

public class Test {
    public static void main(String[] args) {
        //这里可以切换 Vehicle 的 实现类(对象)
        Vehicle vehicle = new Car();
        VehicleProxyProvider vehicleProxyProvider =
                new VehicleProxyProvider(vehicle);
            //看一下 proxy 的结构. Vehicle proxy = vehicleProxyProvider.getProxy();
        System.out.println("proxy 编译类型是 Vehicle");
        System.out.println("proxy 运行类型" + proxy.getClass());
    }
}

解释

动态代理的 动态怎么体现

1. proxy 运行类型是 com.sun.proxy.$Proxy0 该类型被转型成 Vehicle

因此可以调用 Vehicle 的接口方法

2. 当执行 run() 的时候会调用, 根据 Java 的动态绑定机制, 这时直接调用 Car的 run(),而是 proxy 对象的 invocationHandler 的 invoke 方法(!!!!!!)

3. invoke 方法使用反射机制来调用 run()方法注意这个 run 方法也可以是Vehicle 的其它方法)

这时就可以在调用 run()方法前,进行前置处理和后置处理

4. 也就是说 proxy 的 target_vehicle 运行类型只要是实现了 Vehicle 接口

,就可以去调用不同的方法, 是动态的,变化的,底层就是 使用反射完成的. proxy.run();

 😄总结

本篇详细的讲解了Spring-AOP的开始以及通过先动态代理在使用AOP由浅入深更容易理解


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

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

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


目录
相关文章
|
2月前
|
监控 Java 开发者
Spring AOP动态代理
Spring AOP动态代理
48 1
|
1月前
|
监控 Java 数据库连接
Spring高手之路17——动态代理的艺术与实践
本文深入分析了JDK和CGLIB两种动态代理技术在Spring框架中的应用。讨论了动态代理的基础概念,通过实例展示了如何实现和应用这两种方法,并比较了它们的性能差异及适用场景。进一步,探讨了在动态代理中实现熔断限流和日志监控的策略,以及如何利用动态代理优化Spring应用的设计和功能。
42 6
Spring高手之路17——动态代理的艺术与实践
|
1月前
|
Java 数据库 Spring
切面编程的艺术:Spring动态代理解析与实战
切面编程的艺术:Spring动态代理解析与实战
29 0
切面编程的艺术:Spring动态代理解析与实战
|
3月前
|
XML Java 数据格式
浅谈基于动态代理的Spring AOP原理
浅谈基于动态代理的Spring AOP原理
26 0
|
3月前
|
设计模式 安全 Java
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
383 1
|
4月前
|
设计模式 Java Spring
Spring AOP基础之代理模式.静态代理和动态代理
Spring AOP基础之代理模式.静态代理和动态代理
31 0
Spring AOP基础之代理模式.静态代理和动态代理
|
4月前
|
Java Linux iOS开发
Spring5源码(27)-静态代理模式和JDK、CGLIB动态代理
Spring5源码(27)-静态代理模式和JDK、CGLIB动态代理
23 0
|
4月前
|
Java Spring
深入Spring原理-6.动态代理原理分析
深入Spring原理-6.动态代理原理分析
27 0
|
5月前
Spring-动态代理深入了解
Spring-动态代理深入了解
31 0
|
5月前
|
SQL 缓存 Java
【Spring】AOP底层原理(动态代理)-》 AOP概念及术语 -》 AOP实现
【Spring】AOP底层原理(动态代理)-》 AOP概念及术语 -》 AOP实现
31 0