Java动态代理


业务场景

  1. 旧业务
  • 买家调用action,购买衣服,衣服在数据库的标价为50元,购买流程就是简单的调用。
  1. 新业务
  • 在原先的价格上可以使用优惠券,但是这个功能在以前没有实现过,我们通过代理类,代理了原先的接口方法,在这个方法的基础上,修改了返回值。
    mark

代理实现流程

  1. 书写代理类和代理方法,在代理方法中实现代理Proxy.newProxyInstance
  2. 代理中需要的参数分别为:被代理的类的类加载器soneObjectclass.getClassLoader(),被代理类的所有实现接口new Class[] { Interface.class },句柄方法new InvocationHandler()
  3. 在句柄方法中复写invoke方法,invoke方法的输入有3个参数Object proxy(代理类对象), Method method(被代理类的方法),Object[] args(被代理类方法的传入参数),在这个方法中,我们可以定制化的开发新的业务。
  4. 获取代理类,强转成被代理的接口
  5. 最后,我们可以像没被代理一样,调用接口的认可方法,方法被调用后,方法名和参数列表将被传入代理类的invoke方法中,进行新业务的逻辑流程。

原业务接口IBoss

public interface IBoss {//接口
    int yifu(String size);
}

原业务实现类

public class Boss implements IBoss{
    public int yifu(String size){
        System.err.println("天猫小强旗舰店,老板给客户发快递----衣服型号:"+size);
        //这件衣服的价钱,从数据库读取
        return 50;
    }
    public void kuzi(){
        System.err.println("天猫小强旗舰店,老板给客户发快递----裤子");
    }
}

原业务调用

public class SaleAction {
        @Test
    public void saleByBossSelf() throws Exception {
        IBoss boss = new Boss();
        System.out.println("老板自营!");
        int money = boss.yifu("xxl");
        System.out.println("衣服成交价:" + money);
    }
}

代理类

public static IBoss getProxyBoss(final int discountCoupon) throws Exception {
    Object proxedObj = Proxy.newProxyInstance(Boss.class.getClassLoader(),
            new Class[] { IBoss.class }, new InvocationHandler() {
                public Object invoke(Object proxy, Method method,
                        Object[] args) throws Throwable {
                        Integer returnValue = (Integer) method.invoke(new Boss(),
                                args);// 调用原始对象以后返回的值
                        return returnValue - discountCoupon;
                }
            });
    return (IBoss)proxedObj;
}
}

新业务调用

public class ProxySaleAction {
        @Test
    public void saleByProxy() throws Exception {
        IBoss boss = ProxyBoss.getProxyBoss(20);// 将代理的方法实例化成接口
        System.out.println("代理经营!");
        int money = boss.yifu("xxl");// 调用接口的方法,实际上调用方式没有变
        System.out.println("衣服成交价:" + money);
    }
}

推荐阅读更多精彩内容