思考:在IBuyWatermelon添加一个方法selectWatermelon()
静态代理中需要在RealSubject中实现该方法,而且Proxy也要实现该方法调用RealSubject中的实现,如果再增加10个方法还是得这样操作,导致大量的代码重复。
现在来看动态代理(顾名思义,是在运行时才形成的代理对象,不像静态代理在编译时就载入代理对象)。
生成动态代理的方法有很多: JDK中自带的动态代理java.lang.reflect.*, CGlib等
下面的例子是JDK中自带的动态代理java.lang.reflect.*
IBuyWatermelon():接口
package com.maggie.dynamicproxy; public interface IBuyWatermelon { //代理事件 public abstract String buyWatermelon(); public abstract void selectWatermelon(); }
BuyWatermelonImpl:实现类
package com.maggie.dynamicproxy; //可理解成被代理者 public class BuyWatermelonImpl implements IBuyWatermelon { private Supermarket supermaket; public BuyWatermelonImpl(Supermarket supermaket) { super(); this.supermaket = supermaket; } @Override public String buyWatermelon() { System.out.println("在"+supermaket.getName()+" 买西瓜"); return "watermelon"; } @Override public void selectWatermelon() { System.out.println("选择无籽西瓜"); } }
ProxyFactory:代理对象类(核心代码)
package com.maggie.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { //维护一个目标对象 private Object target; public ProxyFactory(Object target){ this.target=target; } //给目标对象生成代理对象 public Object getProxyInstance(){ //动态代理的核心,涉及到反射 return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //执行目标对象方法 Object returnValue = method.invoke(target, args); return returnValue; } } ); } }
客户端调用
package com.maggie.dynamicproxy; public class Main { public static void main(String[] args) { Supermarket zhaoLiu = new Supermarket(); zhaoLiu.setName("赵六超市"); IBuyWatermelon target = new BuyWatermelonImpl(zhaoLiu);//被代理的对象 //创建代理对象 IBuyWatermelon hourskeeper = (IBuyWatermelon) new ProxyFactory(target).getProxyInstance(); hourskeeper.buyWatermelon(); hourskeeper.selectWatermelon(); } }
输出
在赵六超市 买西瓜 选择无籽西瓜
现在就算IBuyWatermelon的方法再怎么增加,也只需要在BuyWatermelonImpl实现,就可以在客户端调用,不会出现大量的重复代码。
从静态代理到动态代理都围绕着卖瓜事件,为了前后方便比较,但是动态代理并没完,里面的源码机制才是核心关键
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)这个方法是整个动态代理实现的关键
时间: 2024-11-05 11:32:21