使用 InvocationHandler 接口 实现动态代理,实现自定义功能的动态增减

InvocationHandler 接口位于 java.lang.reflect 反射包,搭配使用可以实现比较丰富的动态功能增减。

直接上代码:

一:必须有准备实现动态代理的Interface功能接口

/**
 * 准备实现动态代理的接口
 *
 * @author gbx
 */
public interface RunMethodInterface {
    void runA();

    void runB();
}

二:接口的实现类

/**
 * 接口的实现类
 *
 * @author gbx
 */

public class RunMethod implements RunMethodInterface {

    @Override
    public void runA() {
        System.out.println("RunMethod runA...");
    }

    @Override
    public void runB() {
        System.out.println("RunMethod runB...");
    }
}

三:InvocationHandler 接口的自定义实现,主要在这里实现自定义的功能

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * 动态代理测试
 *
 * @author gbx
 */
public class GbxInvocationHandler implements InvocationHandler {

    /**
     * 构造方法引入转化的对象
     */
    private Object object;

    /**
     * InvocationHandler的实现类需要提供一个构造器,用来接收目标对象
     * 否则接口中的method是无法执行的,因为没有对象就没有办法执行对象的方法
     *
     * @param object 要实现代理的对象
     */
    public GbxInvocationHandler(Object object) {
        this.object = object;
    }

    /**
     * Processes a method invocation on a proxy instance and returns
     * the result.  This method will be invoked on an invocation handler
     * when a method is invoked on a proxy instance that it is
     * associated with.
     *
     * @param proxy  the proxy instance that the method was invoked on
     * @param method the {@code Method} instance corresponding to
     *               the interface method invoked on the proxy instance.  The declaring
     *               class of the {@code Method} object will be the interface that
     *               the method was declared in, which may be a superinterface of the
     *               proxy interface that the proxy class inherits the method through.
     * @param args   an array of objects containing the values of the
     *               arguments passed in the method invocation on the proxy instance,
     *               or {@code null} if interface method takes no arguments.
     *               Arguments of primitive types are wrapped in instances of the
     *               appropriate primitive wrapper class, such as
     *               {@code java.lang.Integer} or {@code java.lang.Boolean}.
     * @return the value to return from the method invocation on the
     * proxy instance.  If the declared return type of the interface
     * method is a primitive type, then the value returned by
     * this method must be an instance of the corresponding primitive
     * wrapper class; otherwise, it must be a type assignable to the
     * declared return type.  If the value returned by this method is
     * {@code null} and the interface method's return type is
     * primitive, then a {@code NullPointerException} will be
     * thrown by the method invocation on the proxy instance.  If the
     * value returned by this method is otherwise not compatible with
     * the interface method's declared return type as described above,
     * a {@code ClassCastException} will be thrown by the method
     * invocation on the proxy instance.
     * @throws Throwable the exception to throw from the method
     *                   invocation on the proxy instance.  The exception's type must be
     *                   assignable either to any of the exception types declared in the
     *                   {@code throws} clause of the interface method or to the
     *                   unchecked exception types {@code java.lang.RuntimeException}
     *                   or {@code java.lang.Error}.  If a checked exception is
     *                   thrown by this method that is not assignable to any of the
     *                   exception types declared in the {@code throws} clause of
     *                   the interface method, then an
     *                   {@link UndeclaredThrowableException
     *                   } containing the
     *                   exception that was thrown by this method will be thrown by the
     *                   method invocation on the proxy instance.
     * @see UndeclaredThrowableException
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = null;
        try {
            //执行目标方法前执行的任意逻辑
            System.out.println("GbxInvocationHandler 方法前执行的自定义逻辑...");

            //实现代理的对象方法执行
            invoke = method.invoke(object, args);

            //执行目标方法后执行的任意逻辑
            System.out.println("GbxInvocationHandler 方法后执行的自定义逻辑...");
        } catch (Exception e) {
            System.out.println("GbxInvocationHandler 方法执行异常:" + e.getMessage());
            e.printStackTrace();
        }
        return invoke;
    }
}

四:调用方式

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 测试动态代理
 *
 * @author gbx
 */
public class TestA {
    public static void main(String[] args) {
        RunMethodInterface runMethod = new RunMethod();
        runMethod.runA();
        runMethod.runB();
        System.out.println("============================分割线============================");
        //开始构建自定义代理
        InvocationHandler gbxInvocationHandler = new GbxInvocationHandler(runMethod);
        //成功创建目标对象的代理
        RunMethodInterface proxyRunMethod = (RunMethodInterface) Proxy.newProxyInstance(gbxInvocationHandler.getClass().getClassLoader(), runMethod.getClass().getInterfaces(), gbxInvocationHandler);
        //用代理对象调用相关方法,则执行目标方法和自定义代理中的相关逻辑
        proxyRunMethod.runA();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        proxyRunMethod.runB();
    }
}

五:查看程序执行结果

RunMethod runA...
RunMethod runB...
============================分割线============================
GbxInvocationHandler 方法前执行的自定义逻辑...
RunMethod runA...
GbxInvocationHandler 方法后执行的自定义逻辑...
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GbxInvocationHandler 方法前执行的自定义逻辑...
RunMethod runB...
GbxInvocationHandler 方法后执行的自定义逻辑...

Over!

发布前,看到扯淡的官方提示,说质量低,不会获得推荐。好吧,能看到此博文的皆是有缘之人!

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值