思考:在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;}@Overridepublic String buyWatermelon() {System.out.println("在"+supermaket.getName()+" 买西瓜");return "watermelon";}@Overridepublic 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() {@Overridepublic 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)这个方法是整个动态代理实现的关键