Java的代理及InvocationHandler 接口的用法

编程技术  /  houtizong 发布于 3年前   74
java中是利用InvocationHandler 类实现代理,这是一个回调接口。
其中java代理并不神秘,说穿了就是使用一个和代理对象(也叫目标对象,为免混淆,以下称目标对象)实现了同样接口的一个类(这个类就叫代理类),用户实际是使用这个代理类来完成相关功能,而并不是使用所代理的目标对象本身。其原理是在代理类中有一个目标对象的成员,代理类调用目标成员的方法完成业务。因为这个特点,很容易在调用方法之前或之后来处理一些其它业务,这也就是AOP的实质。
闲话少说,看代码说明问题。不使用InvocationHandler ,我们可以自己这样实现一个简单代理类:
//定义一个接口:interface Greet{    void sayHello(String name);    void goodBye();}//实现这个接口:class GreetImpl implements Greet{    public void sayHello(String name)    {        System.out.println("Hello " + name);    }    public void goodBye()    {        System.out.println("Good bye.");    }}//实现一个代理类public class SimpleProxy implements Greet{    private Greet greet = null;    SimpleProxy(Greet greet)    {        this.greet = greet;    }    public void sayHello(String name)    {        System.out.println("--before method sayHello");        greet.sayHello(name);        System.out.println("--after method sayHello");    }    public void goodBye()    {        System.out.println("--before method goodBye");        greet.goodBye();        System.out.println("--after method goodBye");    }    /**     * @param args     */    public static void main(String[] args)    {        Greet greet = new SimpleProxy(new GreetImpl());//生成代理        greet.sayHello("walter");        greet.goodBye();    }}

再看看如果实现了InvocationHandler接口, 我们怎样实现代理。
还是要实现原来的Greet接口。 接口的实现还是GreetImpl。
import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class DebugProxy implements java.lang.reflect.InvocationHandler{    private Object obj;    public static Object newInstance(Object obj)    {        return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),                obj.getClass().getInterfaces(), new DebugProxy(obj));    }    private DebugProxy(Object obj)    {        //Greet接口的實現:GreetImpl        this.obj = obj;    }    //Method m:調用的方法    //Object[] args:方法要傳入的參數    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable    {        Object result;        try        {            //自定義的處理            System.out.println("--before method " + m.getName());            //調用GreetImpl中方法            result = m.invoke(obj, args);        }        catch(InvocationTargetException e)        {            throw e.getTargetException();        }        catch(Exception e)        {            throw new RuntimeException("unexpected invocation exception: " + e.getMessage());        }        finally        {            System.out.println("--after method " + m.getName());        }        return result;    }    /**     * @param args     */    public static void main(String[] args)    {        Greet tmp = new GreetImpl();                Greet greet = (Greet) DebugProxy.newInstance(tmp);        //生成的greet和tmp有相同的hashCode                greet.sayHello("walter");        greet.goodBye();    }}//注:以上代码转摘自 //http://blog.csdn.net/aladdinty/archive/2009/03/11/3982007.aspx


可以看出,由于java的代理机制,被代理对象必须实现接口。
那如果被代理对象没有实现接口,就没有办法进行代理了吗?当然是可以的,我们可以让代理类继承自被代理对象,这样用户也可以通过父类(被代理类)获取代理对象的引用。Cglib就是这样的实现原理。Cglib中类似于InvocationHandler接口的是MethodInterceptor接口,需要覆写其intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy)方法,看看下面的基于cglib的代理实现:
//引入cglib库略过public class CGlibProxyFactory  implements MethodInterceptor{    privaet Object targetObject;    public Object createProxyIntance(Object targetObject){    this.targetObject = targetObject;Enhnacer enhnacer = new Enhnacer();////cglib实际上创建的代理是目标对象的一个子类,覆盖了父类中所有非final方法    enhnacer.setSuperclass(this.targetObject.getClass());    // setCallback(callback)设置回调对象  callback是实现方法拦截器的一个类    enhnacer.setCallback(this);    return enhnacer.create();}    public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable{        PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;    Object result = null;        if(bean.getUser() != null){    result = methodProxy.invoke(targetObject, args);        }        return result;    }}

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客