JDK动态代理

一、概念

代理设计模式是一种常用的设计模式,为实现某接口的委托对象创造一个代理对象,代码中调用代理对象,代理类进行预处理或者后处理,真正业务逻辑仍然由委托类执行。

JDK动态代理


Java中存在静态代理和动态代理,静态代理需要为每个委托类实际创建一些代理类,如果实现一个接口的几个类均需要代理类,则需要创建多个代理类(也可以创建一个在其中进行路由),比较麻烦。动态代理是JVM在运行过程中利用反射原理创建代理类的字节码文件,代理类和委托类的关系是在运行过程中确定的,不需要写代理类的代码,而且一个代理类可以实现同一接口的多个委托类。

动态代理的缺点:委托了必须实现了某一接口,基于cglib的动态代理避免了这一问题。

二、实现过程

1.首先实现InvocationHandler接口,实现其中的invoke方法。此接口的作用时,通过代理类调用方法时进行拦截,进行一些预处理,然后调用委托类的方法;

2.创建代理类时,需要委托类的类加载器和委托类实现的接口;实际代理类是一个和委托类用统一类加载器加载并且实现统一接口的类。

3.通过Proxy.netProxyIntance()方法获得代理类对象;

4.调用代理类对象调用方法

例子:

public interface Subject {
    void eat();
    void sleep();
}
public class SubjectImp implements Subject{
    public void eat(){
        System.out.println("I want to eat chicken leg!");
    }
    public void sleep(){
        System.out.println("I want to sleep!");
    }
}
public class SubjectInvocationHandler implements InvocationHandler{
    Object obj;
    public SubjectInvocationHandler(Object obj){
        this.obj=obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy:"+proxy.getClass().getName());
        System.out.println("method:"+method);
        return method.invoke(obj,args);
    }
}
public class SubjectMain {
    public static void main(String[] args){
        SubjectImp sub=new SubjectImp();
        SubjectInvocationHandler handler=new SubjectInvocationHandler(sub);
        Subject proxySubject=(Subject) Proxy.newProxyInstance(SubjectImp.class.getClassLoader(),
                SubjectImp.class.getInterfaces(),handler);
        //输出生成的代理类
        System.out.println(proxySubject.getClass().getName());
        //通过代理类调用目标方法
        proxySubject.eat();
    }

输出:

com.sun.proxy.$Proxy0
proxy:com.sun.proxy.$Proxy0
method:public abstract void com.lpq.Subject.eat()
I want to eat chicken leg!