且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

java-动态代理

更新时间:2022-04-01 17:41:04

在学习spring的AOP时候,动态代理那是必不可少的环节。

今天简单介绍一下动态代理。

java动态代理是一种设计模式中代理模式的一种,帮助我们开发的一个工具吧。

*1.动态代理的优势:*

  1. 降低各个功能模块之间的耦合度,提高开发的效率和方便程序的维护度。

  2. 和aop的思想和切合。

  3. 减少代码量。

对静态代理有个了解的读者可能就知道,静态代理的代码量比较庞大,所以动态代理是静态代理的升华。

2.动态代理的实现方式
jdk自带的动态代理主要是通过实现InvocationHandler

2.1 InvocationHandler的主要方法

  • Object invoke(Object proxy,
    Method method,
    Object[] args)
    throws Throwable

  • 在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

2.2 方法详细介绍

  • 参数:
    proxy - 调用方法的代理实例对象 method - 代理实例对象调用的接口方法的 Method 实例对象。
    Method-对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
    args -包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。

  • 返回:
    从代理实例的方法调用返回的值。

  • 抛出: Throwable - 从代理实例上的方法调用抛出的异常。

3.具体登陆日志小案例(基于JDK动态代理)

3.1 业务接口 Login

public interface Login {
    public void login(String name);
}

3.2 业务实现类 LoginImpl

public class LoginImpl implements Login{
    @Override
    public void login(String name) {
        System.out.println("welcome "+name+", login success !!1");
    }
}

3.3 代理类 LoginProxy

public class LoginProxy implements InvocationHandler {

    private Object target;

    public LoginProxy(Object target) {
        this.target = target;
    }

    public static Object init(Object Object){
        return Proxy.newProxyInstance(Object.getClass().getClassLoader(),Object.getClass().getInterfaces(),new LoginProxy(Object));
    }

    /**
     * 切入点 对所有对象的方法都进行调用
     * method.invoke方法对应代理对象调用login方法
     * @param proxy 代理对象
     * @param method 代理对象的方法
     * @param args  代理对象调用接口方法的参数值
     * @return 代理对象调用方法的返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        login(method);
        Object invoke = method.invoke(target, args);
        loginout(method);
        return invoke;
    }

    //日志的方法
    public void log(String msg){
        System.out.println(msg);
    }
    //执行前日志
    public void login(Method method){
        log(method.getName()+"方法执行之前调用的信息");
    }
    //执行后日志
    public void loginout(Method method){
        log(method.getName()+"方法执行之后调用的信息");
    }


}

3.4 测试类 LoginClient

public class LoginClient {
    public static void main(String[] args) {
        Login login = (Login) LoginProxy.init(new LoginImpl());
        login.login("zhangsan");
    }
}

3.5 执行结果:

java-动态代理

从上面的例子我们可以看到动态代理有效的减少了各个模块的耦合度。
用于实现日志功能的代码和用于实现登陆功能的代码相互隔离。
只有在真正调用业务的时候并需要日志功能时候二者才发生联系。
任何业务需要日志功能只需要通过代理类创建代理对象即可。

总结:
代理对象机制是一种非常实用的设计模式,有利于程序的开发效率以及对于程序的后期维护。不必在关系各个模块之间的相互制约关系。