JavaEE - 15动态代理2
(7)反射的应用: 动态代理
(7.1)代理设计模式原理
- 使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。
- 代理对象决定是否以及何时将方法调用转到原始对象上。
- 静态代理,特征是代理类和目标对象的类都是在编译期确定下来的,不利于程序扩展。
- 每个代理类只能为一个接口服务,这样一来就比如产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
- 动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
- 动态代理使用场合:
- 调试
- 远程方法调用
- 动态代理相比于静态代理的优点:
- 抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
(7.2)静态代理
//--接口 public interface ClothFactory { void productCloth(); } // 代理类-------------------- public class ProxyClothFactory implements ClothFactory { // 用被代理类对象进行实例化 private ClothFactory factory; public ProxyClothFactory(ClothFactory factory){ this.factory = factory; } @Override public void productCloth() { System.out.println("代理工厂做准备工作"); factory.productCloth(); System.out.println("代理工厂做收尾工作"); } }
// 被代理类---------------------- public class NikeClothFactory implements ClothFactory{ @Override public void productCloth() { System.out.println("Nike工厂生产Nike运动服"); } }
// 测试---------------------- public class ProxyTest { public static void main(String[] args) { NikeClothFactory nikeClothFactory = new NikeClothFactory(); ProxyClothFactory factory = new ProxyClothFactory(nikeClothFactory); factory.productCloth(); } }
(7.3)动态代理
- 要想实现动态代理,需要解决的问题
- 一是: 如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
- 二是: 当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法。
接口及被代理类
public interface Human { String getBelief(); void eat(String food); } //被代理类 ----------- public class SuperMan implements Human { @Override public String getBelief() { return "I can fly"; } @Override public void eat(String food) { System.out.println("吃"+food); } }
MyInvocationHandler
public class MyInvocationHandler implements InvocationHandler { private Object obj; public void bind(Object obj) { this.obj = obj; } // 当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法: invoke()
// 将被代理要执行的方法a 的功能声明在invoke()中。 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // method: 代理类对象调用的方法,此方法也是被代理类要调用的方法 // obj: 被代理类的对象
Object returnValue = method.invoke(obj, args); return returnValue; } }
ProxyFactory 代理工厂
public class ProxyFactory { // 调用此方法,返回一个代理类的对象,解决问题1 public static Object getProxyInstance(Object obj){ //obj: 被代理类的对象 MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler); } }
测试
public class ProxyTest { public static void main(String[] args){ SuperMan superMan = new SuperMan(); // proxyInstance: 代理类的对象 Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan); // 当通过代理类对象调用方法时,会自动调用被代理类中的同名的方法 String belief = proxyInstance.getBelief(); System.out.println(belief); proxyInstance.eat("四川麻辣烫"); System.out.println("-------------------------"); NikeClothFactory nikeClothFactory = new NikeClothFactory(); ClothFactory clothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory); clothFactory.productCloth(); } }
(7.4)动态代理与AOP(Aspect Orient Programming)
- 代码段1、代码段2、代码段3都同时调用了特定方法A。
- 理想效果:代码段1、2、3既可以执行方法A,又无须在程序中以硬编码的方式直接调用方法A。
- AOP代理方法:
- 动态代理增加的通用方法1
- 回调目标对象的方法
- 动态代理增加的通用方法2
通用方法类HumanUtil
public class HumanUtil { public void method1(){ System.out.println("========通用方法1=========="); } public void method2(){ System.out.println("========通用方法2=========="); } }
MyInvocationHandler方法改进
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // method: 代理类对象调用的方法,此方法也是被代理类要调用的方法 // obj: 被代理类的对象 HumanUtil humanUtil = new HumanUtil(); humanUtil.method1(); Object returnValue = method.invoke(obj, args); humanUtil.method2(); return returnValue; }
执行结果:
========通用方法1========== ========通用方法2========== I can fly ========通用方法1========== 吃四川麻辣烫 ========通用方法2==========
浙公网安备 33010602011771号