标签:
记得刚接触代理,是在大话设计模式,最近在技术总结和学些java的过程又接触到静态代理和动态代理,尤其是动态代理,在学习AOP时,用到了动态代理,下面我用一些例子来对静态代理和动态代理做个总结。
其实用了代理之后最大的好处就是隐藏了真实类(委托类),这样更加安全,而静态代理和动态代理最大的区别就是,静态代理的代理类是程序员自己写的,在程序运行之前就已经存在的,而动态代理则是在程序运行时动态生成的,而且因为动态代理更加灵活,也常被应用。
首先先用一张UML图来理解一下代理是怎么回事?
其实静态代理就是在代理类中放入对为委托类的引用,然后将委托类作为代理类的构造函数的参数,这样在客户端调用时就不会看到委托类了。
1、公共接口,委托类和代理类都来集成它,这样代理类就具有了委托类所有的方法和属性
/*****************公共接口**********************/ public interface ITest { public void addStudent(String Name); }2、委托类,对接口的实现
/******************委托类**********************/ public class Test implements ITest { /** * 执行给定名字的任务。这里打印出学生姓名,并休眠500ms模拟任务执行了很长时间 */ @Override public void addStudent(String Name) { System.out.println("学生姓名:"+Name); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }3、代理类,将委托类的行为表现出来
/**************代理类*******************/ public class ProxyTest implements ITest { // 代理类持有委托类的引用 <span style="color:#ff0000;">private Test delegate;</span> public ProxyTest(<span style="color:#ff0000;">Test delegate</span>) { this.delegate = delegate; } /** * 将请求分派给委托类执行,记录任务执行前后的时间,时间差即为任务的处理时间 */ @Override public void addStudent(String Name) { long stime = System.currentTimeMillis(); // 将请求分派给委托类处理 delegate.addStudent(Name); long ftime = System.currentTimeMillis(); System.out.println("执行任务耗时" + (ftime - stime) + "毫秒"); } }4、代理类工厂
/******** 代理类工厂 ********/ public class TestFactory { public static ITest getInstance() { //对客户类来说,其并不知道返回的是代理类对象还是委托类对象 return new ProxyTest(new Test()); } }
public class Client { /** * @param args */ public static void main(String[] args) { ITest proxy = TestFactory.getInstance(); proxy.addStudent("好学生"); } }那静态代理有什么优缺点呢?为什么会有动态代理产生呢?
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度
动态代理的实现是基于java的三种API的,下面先来介绍一下:
1、java.lang.reflect.Proxy
这是 Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器 static InvocationHandler getInvocationHandler(Object proxy) // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象 static Class getProxyClass(ClassLoader loader, Class[] interfaces) // 方法 3:该方法用于判断指定类对象是否是一个动态代理类 static boolean isProxyClass(Class cl) // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)当然啦,我觉得这些方法不需要记住,只需要在用的时候去查API,多用也就容易上手啦~~
2、java.lang.reflect.InvocationHandler
这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都要指定一个对应的调用处理器对象。
// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象 // 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行 Object invoke(Object proxy, Method method, Object[] args)3、java.lang.ClassLoader(看到java类装载器,突然想到drp的时候还提到了tomcat类装载器)
这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。
每次生成动态代理类对象时都需要指定一个类装载器对象
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/wangdan199112/article/details/47091467