黑马程序员----JAVASE高级部分之动态代理

来源:互联网 发布:象棋打谱软件 编辑:程序博客网 时间:2024/06/06 03:04
-------------- android培训java培训、期待与您交流! ---------------
1.动态代理的理解

代理这个概念不只是java的特有,在现实生活中比比皆是。明星的经纪人,我们可以看做是个代理。在经营品牌电脑的专卖店也可以看做一个代理。其实代理这个概念不是一个新名词,明星的经纪人可以为明星处理很多事,比如:应对记者采访,谈出场费等等,都是由经纪人来解决。而在我们买电脑的时候,我们可以从代理商手里去买到电脑。当然我们也可以到该电脑的生产厂家去买电脑。但是他们的最终目的都是一个,就是你买到电脑。
那么在java中什么是代理那?现在我们要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等,我们就可以使用动态代理了。在java中的动态代理其实实现它的方式很多,sun公司在jdk中为我们提供了Proxy类去实现动态代理,其实不只是sun公司,还有一些第三方的公司为我们提供性能更好的,使用更方便的实现动态代理的手段。比如cglib,在spring框架中spring也使用以上技术封装了自己的动态代理技术。


2.JDK的动态代理

以下为使用jdk的动态代理的框架图

从图中可以看出,其实代理类和目标类是必须实现相同的接口,这也是jdk与cglib实现的区别之处,cglib实现的原理是代理类是目标类的父类,他们是不需要实现相同的接口的。

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: 

1. InvocationHandler:该接口中仅定义了一个方法即:

invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,

method是被代理的方法,args为该方法的参数数组。  

2. Proxy:该类即为动态代理类,其中主要包含以下内容: 
  *  protected Proxy(InvocationHandler handler):构造函数,估计用于给内部的h赋值。 
  *  static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。 
 *  static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用.

一下写一个程序来实现这个动态代理的功能:

目标接口:
package cn.itheima.proxy;public interface TargerInterface {public String getMessage();public void printMessage();}

实现了目标接口的目标类:
package cn.itheima.proxy;public class TargerClass implements TargerInterface{public String getMessage() {return "黑马程序员";}public void printMessage() {System.out.println("黑马程序员");}}

实现了InvocationHandle接口的类:
package cn.itheima.proxy;import java.lang.reflect.Proxy;import java.util.ArrayList;public class InvocationHandleClient {public static void main(String[] args) {TargerClass target = new TargerClass();Advice advice = new Advice();MyInvocationHandle myInvocationHandle = new MyInvocationHandle(target,advice);TargerInterface proxy = (TargerInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInvocationHandle);System.out.println(proxy.getMessage());}}

切面:

package cn.itheima.proxy;public class Advice {public void beforeMethod(){System.out.println("------before method--------");}public void afterMethod(){System.out.println("---------after method----------");}}

客户端测试:
package cn.itheima.proxy;import java.lang.reflect.Proxy;import java.util.ArrayList;public class InvocationHandleClient {public static void main(String[] args) {TargerClass target = new TargerClass();Advice advice = new Advice();MyInvocationHandle myInvocationHandle = new MyInvocationHandle(target,advice);TargerInterface proxy = (TargerInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInvocationHandle);System.out.println(proxy.getMessage());}}


JDK的动态代理必须具备四个条件:

          目标接口

          目标类

          拦截器

          代理类

总结:

1、因为利用JDKProxy生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有。

2、生成的代理类的所有的方法都拦截了目标类的所有的方法。而拦截器中invoke方法的内容正好就是代理类的各个方法的组成体。

          3、利用JDKProxy方式必须有接口的存在。

          4、invoke方法中的三个参数可以访问目标类的被调用方法的API、被调用方法的参数、被调用方法的返回类型。


一个比较经典的jdk动态代理的原理图:


-------------- android培训java培训、期待与您交流! ---------------


原创粉丝点击