简单来说就是代理对象起到中介的作用
流程也就是:使用者 - 代理 - 服务者
用图表示则为:
可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
因为别人写的代码是可以正常运行的,如果随便修改源代码出现bug了就难顶了~
因此如果需要修改,可以通过代理的方式来扩展该方法
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.
我们定义一个接口
public interface Store { void sale(); }然后定义一个实现类
public class StoreImpl implements Store{ @Override public void sale() { System.out.println("卖东西"); } }然后定义代理
public class StoreProxy implements Store { private Store targetObj; public StoreProxy(Store targetObj) { this.targetObj = targetObj; } @Override public void sale() { System.out.println("前驱代码"); targetObj.sale(); System.out.println("后继代码"); } }测试
public class Test { public static void main(String[] args) { Store store = new StoreImpl(); StoreProxy proxy = new StoreProxy(store); proxy.sale(); } }执行结果
前驱代码 卖东西 后继代码一、好处: 可以做到在不修改目标对象的功能前提下,对目标功能扩展.
二、缺点:
①因为代理类需要与实现类实现一样的接口,所以会有很多代理类
②一旦接口增加方法,目标对象与代理对象都需要修改
为了解决这些缺点 我们引入动态代理
动态代理有以下特点: ①.不需要实现接口 ②.代理对象的生成是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型) ③因此动态代理也叫做:JDK代理,接口代理
使用的API
java.lang.reflect.Proxy类的
/** * * @param loader 指定当前目标对象使用类加载器 * @param interfaces :目标对象实现的接口的类型 * @param h 事件处理,执行目标对象的方法时,会触发事件处理器的方法, * 会把当前执行目标对象的方法作为参数传入。简单来说就是=>如何代理 * @return */ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){ }接口和实现类跟静态代理是一样的,就不重复写了.
首先是一个创建代理对象的工厂
package ProxyDemo.DynamicProxyDemo; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { private StoreImpl targetObj; public ProxyFactory(StoreImpl targetObj) { this.targetObj = targetObj; } public Object createProxyInstance(){ return Proxy.newProxyInstance(targetObj.getClass().getClassLoader() , targetObj.getClass().getInterfaces(), (Object proxy, Method method, Object[] args) -> { System.out.println("前驱代码"); //这里args写不写都行 因为是args里啥都没有 Object obj = method.invoke(targetObj,args); System.out.println("后继代码"); return obj; }); } }然后是测试
public class Test { public static void main(String[] args) { StoreImpl obj = new StoreImpl(); Store proxy = (Store) new ProxyFactory(obj).createProxyInstance(); proxy.sale(); } }执行结果
前驱代码 卖东西 后继代码动态代理不需要实现接口,但是目标(实现类)对象通常要实现接口,否则不能用动态代理。
目标对象的方法就是让代理对象调用invoke来执行的
当然我们也可以不写实现类,那么在说明如何代理的时候 也就是传递InvocationHandler h这个参数的时候 说明如何代理即可。换句话说就是把invoke的内容移动到这了而已。
至于不写实现类的例子…咕咕咕,有缘再更