博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
11.JDK动态代理理解与拦截器
阅读量:7040 次
发布时间:2019-06-28

本文共 6005 字,大约阅读时间需要 20 分钟。

1.JDK动态代理

jdk动态代理必须要借助接口才能代理对象,所以先定义接口并实现定义接口 代码如下

package com.day1.com.test1;/** * Created by leewihong on 2018/6/14. */public interface test1_helloworldInterface {    public void sayHelloWorld();}复制代码

接口实现代码

package com.day1.com.test1;/** * Created by leewihong on 2018/6/14. */public class test1_helloworldImpl implements test1_helloworldInterface {    @Override    public void sayHelloWorld() {        System.out.println("sayhelloworld");    }}复制代码

建立代理对象与真实服务对象之间的关系,然后在实现代理逻辑,因此先创建一个代理对象,这个代理对象是需要去实现import java.lang.reflect.InvocationHandler接口,他里面定义了一个invoke方法,并提供接口数组用于下挂代理对象,这一步相当关键,代码如下

package com.day1.com.test1;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * Created by leewihong on 2018/6/14. */public class jdkexampleProxy implements InvocationHandler {    private Object targetImpl = null;    public Object bind(Object targetImpl){        this.targetImpl = targetImpl;//        建立代理对象和真实对象之间的关系        return Proxy.newProxyInstance(targetImpl.getClass().getClassLoader(),targetImpl.getClass                ().getInterfaces(),this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("进入代理逻辑方法");        System.out.println("在调度真实对象之前的服务");//        invoke相当于是调度了真实的方法        Object result = method.invoke(targetImpl,args);        System.out.println("在调度真实对象之后的服务");        return result;    }}复制代码

动态代理测试方法

package com.day1.com.test1;/** * Created by leewihong on 2018/6/14. */public class test1 {    public static void main(String [] args){//        1.test1        jdkexampleProxy jdkexampleProxy = new jdkexampleProxy();        test1_helloworldInterface proxy = (test1_helloworldInterface) jdkexampleProxy.bind(new test1_helloworldImpl());        proxy.sayHelloWorld();    }}复制代码

动态代理测试结果

进入代理逻辑方法在调度真实对象之前的服务sayhelloworld在调度真实对象之后的服务复制代码

验证args参数是否传过去新建另外一个接口

package com.day1.com.test1;/** * Created by leewihong on 2018/6/14. */public interface test1_hellowordinterface2 {    public void sayhelloword2(String name);}复制代码

实现类如下

package com.day1.com.test1;/** * Created by leewihong on 2018/6/14. */public class test1_hellowordimpl2 implements test1_hellowordinterface2{    @Override    public void sayhelloword2(String name) {        System.out.println(name);    }}复制代码

测试代码

package com.day1.com.test1;/** * Created by leewihong on 2018/6/14. */public class test1 {    public static void main(String [] args){//        1.test1        jdkexampleProxy jdkexampleProxy = new jdkexampleProxy();        test1_helloworldInterface proxy = (test1_helloworldInterface) jdkexampleProxy.bind(new test1_helloworldImpl());        proxy.sayHelloWorld();//        2.test2        test1_hellowordinterface2 proxy2 = (test1_hellowordinterface2) jdkexampleProxy.bind(new test1_hellowordimpl2                ());        proxy2.sayhelloword2("weihong");    }}复制代码

输出结果

进入代理逻辑方法在调度真实对象之前的服务sayhelloworld在调度真实对象之后的服务进入代理逻辑方法在调度真实对象之前的服务weihong在调度真实对象之后的服务Process finished with exit code 0复制代码

2.拦截器

拦截器所做的一个目的其实就是需要暴漏一个接口给外部,然后将代理和接口给绑定起来,外部只需要关注接口怎么定义和实现即可

定义拦截器接口

public interface test2_interceptor {    public boolean before(Object proxy, Object target, Method method, Object [] args);    public void around(Object proxy, Object target, Method method, Object [] args);    public void after(Object proxy, Object target, Method method, Object [] args);}复制代码

实现拦截器接口

package com.day1.com.test1.com.test2;import java.lang.reflect.Method;/** * Created by leewihong on 2018/6/14. */public class test2_myinterceptor implements test2_interceptor {    @Override    public boolean before(Object proxy, Object target, Method method, Object[] args) {        System.out.println("反射方法前逻辑");        return false;    }    @Override    public void around(Object proxy, Object target, Method method, Object[] args) {        System.out.println("取代了了被代理对象的方法");    }    @Override    public void after(Object proxy, Object target, Method method, Object[] args) {        System.out.println("反射方法后逻辑");    }}复制代码

在代理中绑定拦截接口

package com.day1.com.test1.com.test2;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * Created by leewihong on 2018/6/14. */public class test2_interceptorJDKProxy implements InvocationHandler {    private Object target = null;    private String interceptorclass = null;    public test2_interceptorJDKProxy(Object target,String interceptorclass){        this.target = target;        this.interceptorclass = interceptorclass;    }    public static Object bind(Object target,String interceptorclass){        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass()                .getInterfaces(),new test2_interceptorJDKProxy(target,interceptorclass));    }    @Override    public Object invoke(Object proxy,Method method, Object[] args) throws            Throwable {        if (interceptorclass == null){//            没有拦截器直接反射原有方法            return method.invoke(target,args);        }        Object result = null;//        通过反射生成拦截器        test2_interceptor test2_interceptor =(test2_interceptor) Class.forName(interceptorclass).newInstance();        if (test2_interceptor.before(proxy,target,method,args))        {//            反射原有对象方法            result = method.invoke(target,args);        }        else {            test2_interceptor.around(proxy,target,method,args);        }        test2_interceptor.after(proxy,target,method,args);        return result;    }}复制代码

测试动态代理拦截器

package com.day1.com.test1.com.test2;import com.day1.com.test1.test1_helloworldImpl;/** * Created by leewihong on 2018/6/14. */public class test2 {    public static void main(String [] args){        test2_helloword proxy = (test2_helloword) test2_interceptorJDKProxy.bind(new                test2_hellowordImp(),"com.day1.com.test1.com.test2.test2_myinterceptor");        proxy.sayhelloword();    }}复制代码

得到结果

反射方法前逻辑取代了了被代理对象的方法反射方法后逻辑复制代码

转载于:https://juejin.im/post/5c2732e56fb9a049b221f677

你可能感兴趣的文章
统计函数——汇总统计时间类数据
查看>>
精进不休 .NET 4.0 (6) - ADO.NET Data Services 1.5 新特性
查看>>
android 布局页面文件出错故障排除Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V...
查看>>
熄灯问题
查看>>
引用类型参数,ref按引用传值
查看>>
基于Widnows Server 2003 SP2的系统需要新的系统准备工具
查看>>
C++ 制作 json 数据 并 传送给服务端(Server) 的 php
查看>>
如何从VS2003升级到VS2008
查看>>
Kernel内核的裁剪及移植(三)
查看>>
Oracle10g Bug 4612267 补丁安装备忘录
查看>>
我的Android开源项目:JNote
查看>>
跨线程操作UI
查看>>
关于Unity加载优化,你可能遇到这些问题
查看>>
在 Windows 7 和 Windows Server 2008 R2 上安装 Windows PowerShell 3.0
查看>>
专访IBM Power总经理 纵览Power 7新特性
查看>>
如何选购台式电脑和笔记本?购买时应注意什么
查看>>
Spring MVC基于注解来格式化数据
查看>>
mysql主从同步错误解决和Slave_IO_Running: NO
查看>>
编码问题之:java.io.UTFDataFormatException: Invalid byte 2 of 2-byte UTF-8 sequence.
查看>>
配置samba服务
查看>>