zoukankan      html  css  js  c++  java
  • jdk动态代理

    java实现动态代理所需的类或接口:

    在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

    1.InvocationHandler

    每一个动态代理类都必须要实现InvocationHandler接口,并且每个代理类的实列都关联了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的的invoker 方法来进行,我们来看看InvocationHandler接口的唯一一个方法invocker方法:

    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable;

    这个方法一共接收三个参数,那么这三个参数分别代表如下:

    proxy:指代JDK动态生成的最终代理对象

    method:指代的是我们所要调用真实对象的某个方法的method对象

    args:指代的是调用真实对象某个方法时接受的参数。

    2.Proxy

    Proxy这个类的作用就是用来动态创建衣蛾代理对象的类,它提供了许多方法,

    但是我们用的最多的就是newProxyInstance这个方法:

    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException

    这个方法的作用就是得到一个动态的代理对象,其接受三个参数,我们来看看这三个参数,

    loader:一个ClassLoader对象,定义了由哪个ClassLoader来对生成的代理对象进行加载,

    interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,

    如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。

    InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上,其实我们所说的DynamicProxy(动态代理类)是这样一种class:它是在运行时生成的class,如此一来,我们可以把该class的实列当做这些interface中的任何一个来用(可以强转为相应的接口类型)。当然,这个DynamicProxy其实就是一个Proxy,他不做作任何实质性的工作,在生成它的实列时你必须提供一个Handler,由它接管实际工作(即调用invocker方法)。

    3.具体实例

    //需要动态代理的接口
    public interface Subject {
    public void hello(String name);
    public String bye();

    }

    //实现接口的实例

    public class RealSubject implements Subject{

    @Override
    public void hello(String name) {
    System.out.println("hello"+name);
    }

    @Override
    public String bye() {
    System.out.println("bye");
    return "bye";
    }

    }

    //每次生成动态代理对象时都需要指定一个实现了InvocationHandler接口对象
    public class InvocationHandlerImpl implements InvocationHandler{
    private Object subject;//这个就是我们要代理的真实对象,也就是真正执行业务逻辑的类

    //通过构造方法传入这个被代理对象
    public InvocationHandlerImpl(Object subject){
    this.subject=subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result=null;
    System.out.println("可以在调用实际方法前做一些事情");
    System.out.println("当前调用的方法是" + method.getName());
    // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
    result = method.invoke(subject, args);// 需要指定被代理对象和传入参数
    System.out.println(method.getName() + "方法的返回值是" + result);
    System.out.println("可以在调用实际方法后做一些事情");
    System.out.println("------------------------");
    return result;// 返回method方法执行后的返回值
    }

    public Object getProxy(){
    return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),subject.getClass().getInterfaces() , this);

    }

    //测试类:

    public class Test {

    public static void main(String[] args) {
    //被代理的对象
    Subject subject=new RealSubject();
    InvocationHandlerImpl handler=new InvocationHandlerImpl(subject);
    Subject proxy=(Subject) handler.getProxy();
    System.out.println("动态代理对象的类型:"+subject.getClass().getName());
    proxy.hello("tom");
    proxy.bye();
    }




    }

    //测试结果:

    动态代理对象的类型:com.newtouch.invoker.RealSubject
    可以在调用实际方法前做一些事情
    当前调用的方法是hello
    hellotom
    hello方法的返回值是null
    可以在调用实际方法后做一些事情
    ------------------------
    可以在调用实际方法前做一些事情
    当前调用的方法是bye
    bye
    bye方法的返回值是bye
    可以在调用实际方法后做一些事情
    ------------------------

  • 相关阅读:
    第三章第四章总结
    java学习2打架代码编写
    windows server 2008 远程桌面(授权、普通用户登录)
    Windows组建网络服务 ——WEB服务器的组建与架构
    windows server 2008 站点系列
    将 Ubuntu 加入到 Windows 2003 AD域
    Windows Server 2008组策略管理与配置
    AD用户设置系列
    利用windows 2003实现服务器群集的搭建与架设
    server2008 跨进新的平台(三)高端的备份还原工具
  • 原文地址:https://www.cnblogs.com/caibixiang123/p/9050666.html
Copyright © 2011-2022 走看看