Java动态代理

306

什么是代理

代理一词顾名思义就是间接的代替委托者完成一些事,生活中常见的中介、旅行社等等都是一些代理;
而代理模式也是Java中比较重要的一种设计模式,目的也是为其他对象提供一种代理以控制对这个对象的访问。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口。

动态代理的用途

动态代理的用途与装饰模式很相似,就是为了对某个对象进行增强。

动态代理相关接口、类的介绍

Interface InvocationHandler

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

Object invoke(Object targetObject, Method method, Object[] args)
  1. targetObject : 需要被代理的对象
  2. method : 被代理对象的某个方法
  3. args : 相对于被调用方法来说的实参
  4. 返回的Object : 这个是调用被代理对象的方法的返回的值
其次是重要的PROXY类,它是JAVA.LANG.REFLECT包下的
Class Proxy

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

创建动态代理我们常用的方法就是如下的静态方法:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
  1. loader : 代理类的类加载器
  2. interfaces : 代理类实现的一个或者多个接口
  3. h : 指派方法调用的调用处理程序
  4. 返回的Object : 一个增强的代理角色

简单的例子

首先是代理以及委托者都需要实现的接口

//售票处
public interface Tiketing {
    public void sellTicket(String plan);
}

其次是委托者

//代理商
public class Agent implements Tiketing {
   @Override
   public void sellTicket(String plan) {
       System.out.println("你要去" + plan + ",需要支付10000元");
   }
}

用例:


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

    //代理商要向顾客卖票要收取辛苦费
    public class Test {
    //  public void fun1() {
    //      Tiketing agent = new Agent();
    //      agent.sellTicket("日本");
    //  }

        public void fun2() {
            //谁调用就用谁的类加载器加载
            ClassLoader loader = this.getClass().getClassLoader();
            //需要增强类的实现的接口
            Class[] interfaces = {Tiketing.class};
            //
            InvocationHandler agentinvocation = new AgentInvocationHandler(new Agent());
            //增强的对象
            Tiketing agent = (Tiketing) Proxy.newProxyInstance(loader, interfaces, agentinvocation);
            agent.sellTicket("日本");

        }

        public static void main(String[] args) {
            //new Test().fun1();
            new Test().fun2();
        }

    }

    class AgentInvocationHandler implements InvocationHandler {
        private Agent agent;
        //传入需要增强的对象
        public AgentInvocationHandler(Agent agent) {
            this.agent = agent;
        }

        @Override
        public Object invoke(Object obj, Method me, Object[] param) throws Throwable {
            System.out.println("请给辛苦费1000元!");
            me.invoke(agent, param);
            System.out.println("谢谢你,欢迎下次再来");
            return null;
        }
    }

通用的动态代理工厂

需要增强功能的对象之前的增强内容

    //前置增强
    public interface Advance {
        public void beforeMethod();
    }

需要增强功能的对象之后的增强内容

    //后置增强
    public interface After {
        public void afterMethod();
    }

代理对象与被增强对象需要共同实现接口

    public interface Ticketing {
        public void sellTicket(String plan);
    }

被增强对象实现接口

public class Agent implements Ticketing {

        public Agent() {}

        @Override
        public void sellTicket(String plan) {
            System.out.println("你要去" + plan + ",需要支付10000元!");
        }
    }

代理工厂

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

    public class ProxyFactory {
        //前置增强
        private Advance advance;
        //后置增强
        private After after;
        //增强对象
        private Object targetObject;

        public ProxyFactory() {}

        public Advance getAdvance() {
            return advance;
        }

        public void setAdvance(Advance advance) {
            this.advance = advance;
        }

        public After getAfter() {
            return after;
        }

        public void setAfter(After after) {
            this.after = after;
        }

        public Object getTargetObject() {
            return targetObject;
        }

        public void setTargetObject(Object targetObject) {
            this.targetObject = targetObject;
        }

        public Object createProxy() {
            //获取类加载器
            ClassLoader loader = this.getClass().getClassLoader();
            //获取目标对象实现的接口
            Class[] interfaces = this.targetObject.getClass().getInterfaces();
            //调用的处理器
            InvocationHandler handler = new InvocationHandler() {
                @Override
                public Object invoke(Object obj, Method me, Object[] params) throws Throwable {
                    //添加前置增强
                    if(advance != null) {
                        advance.beforeMethod();
                    }
                    //调用平常的方法
                    Object result = me.invoke(targetObject, params);
                    //后置增强
                    if(after != null) {
                        after.afterMethod();
                    }
                    return result;
                }};

            return Proxy.newProxyInstance(loader, interfaces, handler);
        }
    }

对代理工厂的简单的测试

    public class Test {

        public static void main(String[] args) {
            //创建代理工厂
            ProxyFactory factory = new ProxyFactory();

            //被增强对象
            Agent agent = new Agent();
            factory.setTargetObject(agent);
            //前置增强
            factory.setAdvance(new Advance() {
                public void beforeMethod() {
                    System.out.println("你需要购票之前支付辛苦费2500元");
                }
            });
            //后置增强
            factory.setAfter(new After() {
                public void afterMethod() {
                    System.out.println("谢谢你的惠顾,下次再来");
                }
            });

            //获得增强的代理对象
            Ticketing ticketAgent = (Ticketing) factory.createProxy();
            //卖票
            ticketAgent.sellTicket("日本");
        }
    }