Java静态代理与动态代理实战解析

Java静态代理

示例代码

接口:

java 复制代码
package com.ssg.aop.interfaces;

public interface MathCalculator {
//    加法
    public int add(int a, int b);
}

接口实现类:

java 复制代码
package com.ssg.aop.impl;
import com.ssg.aop.interfaces.MathCalculator;

public class MathCalculatorImpl implements MathCalculator {
    @Override
    public int add(int a, int b) {
        int i = a + b;
        System.out.println("方法执行结果 = " + i);
        return i;
    }
}

静态代理类:

  • 静态代理类继承接口文件,重写方法
  • 静态代理类通过构造器来引入原代理类。
java 复制代码
package com.ssg.aop.proxy.statics;
import com.ssg.aop.interfaces.MathCalculator;

public class MathCalculatorStaticProxy implements MathCalculator {

//    接口倒置,注入接口,而不是实现类
    private MathCalculator mathCalculator;

    public MathCalculatorStaticProxy(MathCalculator mathCalculator) {
        this.mathCalculator = mathCalculator;
    }

    /**
     * @param a
     * @param b
     * @return
     */
    @Override
    public int add(int a, int b) {
        System.out.println("开始 >>> a + b == " + a + "+" + b);
        int add = mathCalculator.add(a, b);
        System.out.println("结束 >>> a + b = " + add);
        return add;
    }
}

@Test测试类

java 复制代码
public class TestMathCalculator {

    @Test
    public void testAdd() {
        MathCalculator mathCalculatorImpl = new MathCalculatorImpl();
        MathCalculator calculator = new MathCalculatorStaticProxy(mathCalculatorImpl);
        int result = calculator.add(1, 2);
        System.out.println("Test add result = " + result);
    }
}

Java原生动态代理

Java原生动态代理,缺点是:代理对象必须是接口,没有接口无法代理。为所有方法进行代理,不能灵活操控。

示例代码

接口文件、接口实现类、动态代理类、Test类。

接口和接口实现类

沿用静态代理中的接口和接口实现类。

动态代理类:

写法一

核心:类加载器、类接口、InvocationHandler逻辑类其作用为:动态代理的具体逻辑代码写在该处。
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);

java 复制代码
package com.ssg.aop.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class MathCalculatorDynamicProxy {

    public static Object getDynamicProxy(Object object) {
        // object:目标对象,被代理的对象

        // 第一个参数:需要类加载器,通过反射获取
        // 第二个参数:需要获取类接口(被代理对象的接口)信息,通过反射
        // 第三个对象:代理逻辑,怎么去代理
        return Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("动态代理执行前:" + Arrays.toString(args));
                        Object invoke = method.invoke(object, args);
                        System.out.println("动态代理执行后:" + invoke.toString());
                        return invoke;

                    }
                }
        );
    }
}
写法二:
java 复制代码
    /**
     * 动态代理,代理所有类方法
     * @param mathClass 被代理的对象,数学计算器类
     * @return
     */
    public static Object getProxyInstance(Object mathClass) {
        
        InvocationHandler invocationHandler = new InvocationHandler() {
            /**
             * @param proxy  代理
             * @param method 代理方法,被调用方法
             * @param args 代理方法的参数,被调用的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("动态代理执行前:" + Arrays.toString(args));
                Object invoke = method.invoke(mathClass, args);
                System.out.println("动态代理执行后:" + invoke.toString());
                return invoke;
            }
        };
        
        // 返回 动态代理类
        return Proxy.newProxyInstance(mathClass.getClass().getClassLoader(), mathClass.getClass().getInterfaces(), invocationHandler);
    };

@Test测试类:

java 复制代码
package com.ssg.aop;

import com.ssg.aop.impl.MathCalculatorImpl;
import com.ssg.aop.interfaces.MathCalculator;
import com.ssg.aop.proxy.dynamic.MathCalculatorDynamicProxy;
import org.junit.jupiter.api.Test;

public class DynamicTest {

    @Test
    public void test() {
        MathCalculator mathCalculator = new MathCalculatorImpl();
        MathCalculator dynamicProxy = (MathCalculator) MathCalculatorDynamicProxy.getDynamicProxy(mathCalculator);
        int add = dynamicProxy.add(1, 2);
        System.out.println("测试方法执行结果为 = " + add);
    }
}

结果输出:

复制代码
动态代理执行前:[1, 2]
方法执行结果 = 3
动态代理执行后:3
测试方法执行结果为 = 3