Java动态代理机制之JDK动态代理

版权声明:本文为博主原创文章,转载请附上链接。 https://blog.csdn.net/qq_36182135/article/details/82686801

代理模式(Proxy Pattern)是23种常用的面向对象软件的设计模式之一,作用是为其他对象提供一种代理以控制对这个对象的访问,直白说就是中间商或代购。如图。client发起请求到接口,正常是通过接口实现类impl来调用方法完成请求,但是增加了代理类后,可以直接用proxy的实例来调用interface的实现类的方法,并且可以增加额外的功能。

为什么要增加一层代理类呢,有两个优点:

1. 隐藏和保护接口实现类, 控制对接口实现类对象的直接访问

2. 可以增加新的功能实现,提高了系统的可扩展性

JDK动态代理是常用的代理机制之一,主要是通过反射来实现的,实现JDK动态代理,必须要实现 InvocationHandler 接口,实现这个接口同时,会要求重写invoke()方法,如下,参数列表中

proxy:动态代理类(给你代购的那个人)

method:被调用的方法

args:被调用的方法的参数

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

来写个实例展示动态代理的调用过程

首先是接口,写了一个方法,并重载了这个方法

package pers.hong;

/**
 * @Description:
 * @Auther: hong
 * @Date: 2018/09/13
 */
public interface TicketProvider {
    public void getTrainTicket();
    public void getTrainTicket(int count);
}

然后是它的实现类

package pers.hong;

/**
 * @Description:
 * @Auther: hong
 * @Date: 2018/09/13
 */
public class TicketProviderImpl implements TicketProvider {

    @Override
    public void getTrainTicket() {
        System.out.println("购买火车票");
    }

    @Override
    public void getTrainTicket(int count) {
        System.out.println("购买火车票"+count+"张");
    }
}

然后是代理类,实现了InvocationHandler接口,重写了invoke方法

package pers.hong;

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

/**
 * @Description:
 * @Auther: hong
 * @Date: 2018/09/13
 */
public class TicketProviderProxy implements InvocationHandler {
    //实际对象,也就是代购要去的商店
    private Object target;

    //构造器赋值
    public TicketProviderProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-----before in method invoke-----");
        //invoke()方法通过是实际对象和参数,找到对应的方法
        method.invoke(target, args);
        System.out.println("Add functionality to the method");
        System.out.println("-----after in method invoke-----");
        return null;
    }
}

然后就是代理测试

package pers.hong;

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

/**
 * @Description:
 * @Auther: hong
 * @Date: 2018/09/13
 */
public class ProxyTest {
    public static void main(String[] args) {
        //接口实现类
        TicketProvider ticketProvider = new TicketProviderImpl();
        //InvocationHandler实现类,用到了刚才定义的构造器
        InvocationHandler handler = new TicketProviderProxy(ticketProvider);
        //newProxyInstance()生成动态代理类实例,args[0]是实现类,args[1]是要接口类,
        //args[2]是InvocationHandler实现类,即处理器,处理传入的需要被代理的真实对象
        TicketProvider ticketProviderProxy = (TicketProvider) Proxy.newProxyInstance(
                ticketProvider.getClass().getClassLoader(),
                ticketProvider.getClass().getInterfaces(),
                handler);
        //传入参数测试
        ticketProviderProxy.getTrainTicket();
        ticketProviderProxy.getTrainTicket(5);
    }
}

输出结果为

可以看到,通过newProxyInstance()方法创建的代理对象可以调用到接口实现类的方法,并且还输出了增加的的方法。这样动态代理就实现了。

反射的使用地方在于,动态代理类proxy的生成,即newProxyInstance()方法,他实现了第二个参数,也就是接口类,然后在实现接口方法的内部,通过反射调用了handler的invoke()方法,invoke()方法再通过内部的method.invoke()校验传入的参数,然后根据参数的不同去调用接口实现类的方法。

这点在SpringAOP中的实现也是一样的,只不过AOP的动态代理机制多了cglib动态代理,用来代理没有实现接口的对象。像bean这种,就是用cglib来进行代理的。

demo地址:https://github.com/hong52ni/Dynamic-proxy

猜你喜欢

转载自blog.csdn.net/qq_36182135/article/details/82686801