静态代理 & 动态代理
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
静态代理就是用接口实现向上转型,通过实现类重写方法实现代理增强
// 定义接口 public interface IAnimal { void eat(); } /** * 目标对象实现了某一个接口 */ public class Cat implements IAnimal { @Override public void eat() { System.out.println("小猫爱吃鱼"); } } /** * 静态代理 * 代理对象和目标对象实现相同的接口 */ public class AnimalProxy implements IAnimal { //使用接口对象 接收目标对象 private IAnimal target; public AnimalProxy(IAnimal target) { this.target = target; } // 对对象的 eat() 方法进行功能扩展, 代理增强 @Override public void eat() { System.out.println("小猫是一只布偶哦!"); target.eat(); } //测试使用 public static void main(String[] args) { //目标对象 IAnimal target = new Cat(); //代理对象 IAnimal proxy = new AnimalProxy(target); // 执行代理的方法 proxy.eat(); } }
运行结果:

动态代理,通过反射机制,运行时创建代理类,
/** * JDK动态代理 使用反射机制 * 动态代理不需要实现接口,但需要指定接口类型 */ public class DynamicProxy { //维护一个目标对象 private Object target; public DynamicProxy(Object target) { this.target = target; } public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * @param proxy 代理者,如果想对代理者做一些操作可以使用这个参数 * @param method 被执行的方法, * @param args 执行该方法所需要的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method excute!"); System.out.println("but i love dog more!"); //1. 传入的对象通过反射获取数据 Object resObj = method.invoke(target, args); System.out.println("after method excute!"); return resObj; } } ); } public static void main(String[] args) { IAnimal cat = new Cat(); IAnimal iAnimal = (IAnimal) new DynamicProxy(cat).getProxyInstance(); iAnimal.eat(); } }

public class DynamicProxy1 implements InvocationHandler { private Object target; public DynamicProxy1(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method excute !"); Object obj = method.invoke(target, args); System.out.println("after method excute !"); return null; } public static void main(String[] args) { System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); IAnimal cat = new Cat(); DynamicProxy1 handle = new DynamicProxy1(cat); IAnimal iAnimal = (IAnimal) Proxy.newProxyInstance(cat.getClass().getClassLoader(), cat.getClass().getInterfaces(), handle); iAnimal.eat(); } }

上面为代理实现一个接口的情况, 如果此时还有一个宠物医院的接口(不同接口),需要给小猫治病,此时,如果使用静态代理, 则需要手动编写一个医院代理类,然后进行代理处理,以此方式,如果有N多个接口需要进行代理处理,则需要些N多个代理类,代码量庞大; 动态代理则可已解决此问题,根据传入的对象进行反射,可拿到不同的需要代理的对象,执行方法。
例如:
// 宠物医院接口 public interface IAnimalHospital { // 医院治疗方法 void care(); } /** * 需要代理的对象, 小猫宠物医院,实现方法对小猫进行治疗 */ public class CatHospital implements IAnimalHospital{ @Override public void care() { System.out.println("给小猫进行治疗"); } } /** * JDK动态代理 使用反射机制 * 动态代理不需要实现接口,但需要指定接口类型 */ public class DynamicProxy { //维护一个目标对象 private Object target; public DynamicProxy(Object target) { this.target = target; } public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * @param proxy 代理者,如果想对代理者做一些操作可以使用这个参数 * @param method 被执行的方法, * @param args 执行该方法所需要的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method excute!"); System.out.println("but i love dog more!"); //1. 传入的对象通过反射获取数据 Object resObj = method.invoke(target, args); System.out.println("after method excute!"); return resObj; } } ); } public static void main(String[] args) { IAnimal cat = new Cat(); IAnimal iAnimal = (IAnimal) new DynamicProxy(cat).getProxyInstance(); iAnimal.eat(); IAnimalHospital careCat = new CatHospital(); IAnimalHospital iAnimalHospital = (IAnimalHospital) new DynamicProxy(careCat).getProxyInstance(); iAnimalHospital.care(); } }

个人理解,如有错误,烦请指正
浙公网安备 33010602011771号