静态代理的优点:拓展函数功能。
静态代理的缺点:如果接口中加了方法,既需要对目标对象类进行维护又要对代理对象类维护,维护工作较多,不过灵活,另外代理类一多,就需要建立很多类。
动态代理以一代多,灵活处理。
1、创建ComInterface 接口
package cn.ecut.test.utils; public interface ComInterface { void sayHi(); }
2、创建代理工厂类
package cn.ecut.test.utils; 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; } /** * 返回一个指定接口的代理类实例 * @return */ 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 { System.out.println("------开始拓展目标方法------"); //执行目标对象中的原方法 Object obj = method.invoke(target,args); System.out.println("------结束拓展目标方法------"); return obj; } }); } }
说明:代理工厂类必须要有一个Object 属性来接收目标对象,一个getProxyInstance()返回代理对象实例的方法。
其中的 InvocationHandler 是一个接口,此处是利用匿名内部函数的好处(当只需要创建一个对象的时候使用匿名内部函数),new InvocationHandler(){...} 是一个匿名函数的使用
返回的是一个实例化InvocationHandler接口的对象。这就是为什么能在这个接口面前使用new关键字。
3、目标对象
package cn.ecut.test.utils; public class TargetObject implements ComInterface{ @Override public void sayHi() { System.out.println("-----很高兴见到你!-----"); } }
4、调试类
package cn.ecut.test.utils; public class ProxyTest { public static void main(String[] args) { ComInterface target = new TargetObject(); ComInterface proxy = (ComInterface) new ProxyFactory(target).getProxyInstance(); proxy.sayHi(); } }
5、测试结果
6、总结:
通过创建代理工厂来管理所有的代理类,减少代码冗余,当哪个类中哪个方法需要拓展功能就可以通过这种方法来解决了。
在创建动态工厂的时候需要注意:1、必须要一个接收目标对象的属性 Object target
2、一个返回代理对象的方法 getProxyInstance()