博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态代理
阅读量:6830 次
发布时间:2019-06-26

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

增强的手段

1、继承
*被增强对象不能变
*增强内容不能变
2.装饰者模式
*被增强对象可变
*但增强内容不可变
3.动态代理
*被增强对象可变
*增强内容可变

 

首先一个方法:

Proxy.newProxyInstance(ClassLoader classLoader,Class[] interfaces,invocationHandler h);

1、方法作用:动态创建实现了interfaces数组中所有指定接口的实现类对象!

参数:

1、ClassLoader:类加载器

它是用来加载类的,把.class文件加载到内存形成Class对象!
2、Class[] interfaces:指定要执行的接口
3、invocationHandler:代理对象的所有方法(个别方法不执行)都会调用InvocationHandler的invoke方法

 

第一个测试类:

package com.itcast.demo1;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.junit.Test;public class Demo1 {    @Test    public void fun1(){        /*         * 三大参数         * 1.ClassLoader         * 方法需要动态生成一个类,这个类实现了A、B接口,然后创建这个类的对象!         * 需要生成一个类,这个类也需要加载到方法区中,谁来加载,当然是ClassLoader         *         * 2.Class[] interfaces         * 它是要实现的接口们         *          * 3.InvocationHandler         * 它是调用处理器         * 敷衍它         *          * 代理对象的所有方法都是调用invocationHandler的invoke方法         */        ClassLoader loader=this.getClass().getClassLoader();        InvocationHandler h=new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args)                    throws Throwable {                System.out.println("你好,动态代理!");                return null;            }        };        //使用三大参数创建代理对象        Object o=Proxy.newProxyInstance(loader, new Class[]{A.class,B.class}, h);                //强转成A和B类型,成功了!        A a=(A) o;        B b=(B) o;        a.a();        b.b();        a.aa();        b.bb();        System.out.println(a.getClass().getName());            }}interface A{    public void a();    public void aa();}interface B{    public void b();    public void bb();}

证实几点:

  1、该方法生成了实现指定接口的代理对象。

  2、代理类的几乎所有方法的执行都是调用invocation的invoke方法。

  3、类加载器使用this.getClass().getClassLoader()得到。

 

动态代理的作用

最终是学习AOP(面向切面编程),它与装饰者模式有点相似,它比装饰者模式还要灵活!

 

方法:

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

这个invoke方法什么时候被调用!

1、在代理对象呗创建时?错误的
2、在调用代理对象所实现接口中的方法时?正确的!

*Object proxy:当前对象,即代理对象!在调用谁的方法!

*Method method:当前被调用的方法(目标方法)
*Object[] args:实参!

 

实现

(*被增强对象可变*但增强内容不可变):

package com.itcast.demo2;//服务员public interface Waiter {    //服务    public void server();}package com.itcast.demo2;public class ManWaiter implements Waiter {    @Override    public void server() {        System.out.println("服务中!");    }}package com.itcast.demo2;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.junit.Test;/** * 我们必须要掌握的是当前这个案例! * @author Administrator * */public class Demo2 {    @Test    public void fun1(){        Waiter manWaiter=new ManWaiter();        /*         * 给出三个参数,来调用方法得到代理对象         */        ClassLoader loader=this.getClass().getClassLoader();        Class[] interfaces={Waiter.class};        InvocationHandler h=new WaitInvocationHanlder(manWaiter); //被增强的目标对象        Waiter waiter=(Waiter) Proxy.newProxyInstance(loader, interfaces, h);                waiter.server();//前面加你好,后面加再见    }    }class WaitInvocationHanlder implements InvocationHandler{    private Waiter waiter;//目标对象    public WaitInvocationHanlder(Waiter waiter){        this.setWaiter(waiter);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        System.out.println("你好!");        this.waiter.server();//调用目标对象的方法        System.out.println("再见!");        return null;//return 的值是执行的方法的返回值,这个方法的proxy表示的是本代理对象,所以不能使用method.invoke(proxy,args).这样会走死循环。    }    public void setWaiter(Waiter waiter) {        this.waiter = waiter;    }    public Waiter getWaiter() {        return waiter;    }    }

 

 

使用工厂模式,实现增强内容也可变。

目标对象:被增强的对象

代理对象:需要增强的对象,
目标:

  执行前增强

  执行后增强

 

package com.itcast.demo3;/** * 前置增强 */public interface BeforeAdvice {    public void before();}package com.itcast.demo3;/* * 后置增强 */public interface AfterAdvice {        public void after();}package com.itcast.demo3;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 它用来生成代理对象 * 它需要所有的参数 *     *目标对象 *  *增强 *//** * 1、创建代理工厂 * 2、改工厂设置三样东西: *     *目标对象setTargetObject *     *前置增强:setBeforeAdvice *     *后置增强:setAfterAdvice * 3、调用createProxy()得到代理对象 *     *执行代理对象方法时: *         执行BeforeAdvice的before() *         目标对象的目标方法 *         执行AfterAdvice的after() */public class ProxyFactory {    private Object targetObject;//目标对象    private BeforeAdvice beforeAdvice;//前置增强    private AfterAdvice afterAdvice;//后置增强    public Object getTargetObject() {        return targetObject;    }        /**     * 用来生成代理对象     * @return     */    public Object createProxy(){        /*         * 给出三大参数         */        ClassLoader loader=this.getClass().getClassLoader();        Class[] interfaces=targetObject.getClass().getInterfaces();        InvocationHandler h=new InvocationHandler() {                        @Override            public Object invoke(Object proxy, Method method, Object[] args)                    throws Throwable {                /*                 * 在调用代理对象的方法时,执行这里的内容                 */                //执行前置增强                if(beforeAdvice!=null){                    beforeAdvice.before();                }            Object result=method.invoke(targetObject, args);//执行目标对象的目标方法                //执行后置增强                if(afterAdvice!=null){                    afterAdvice.after();                }                //返回目标对象中的返回值                return result;            }        };                //得到代理对象        Object obj=Proxy.newProxyInstance(loader, interfaces, h);                //返回代理        return obj;    }                public void setTargetObject(Object targetObject) {        this.targetObject = targetObject;    }    public BeforeAdvice getBeforeAdvice() {        return beforeAdvice;    }    public void setBeforeAdvice(BeforeAdvice beforeAdvice) {        this.beforeAdvice = beforeAdvice;    }    public AfterAdvice getAfterAdvice() {        return afterAdvice;    }    public void setAfterAdvice(AfterAdvice afterAdvice) {        this.afterAdvice = afterAdvice;    }    }

主要代码就这些:

这里实现增强内容可变的方法是代理对象的执行体令它是可变的,所以使用工厂进行创建,进行了一些包装操作。我们必须透彻理解如何进行的增强,增强的步骤等。

难点在于:

  1、思路。明确知道自己需要什么怎么办。

  2、proxy中的invoke方法的书写。

转载地址:http://fynkl.baihongyu.com/

你可能感兴趣的文章
jQuery内容过滤选择器再探究(原创)
查看>>
OpenCV——级联分类器(CascadeClassifier)
查看>>
Ajax 访问 或 获取 IIS 虚拟目录
查看>>
Palindrome POJ 1159 动态规划
查看>>
lua的C库
查看>>
poj - 1236 Network of Schools
查看>>
面向对象程序设计进阶(二)
查看>>
通用输入输出端口 - GPIO
查看>>
JSP内置对象和EL内置对象
查看>>
Python开发【第十九篇】:Python操作MySQL
查看>>
oracle单词
查看>>
从头开始db-oracle
查看>>
Python3学习笔记25-logging模块
查看>>
RHEL6.5 LVM使用解析
查看>>
Windows 8 应用商店正式面向全部开发者开放
查看>>
lamp系列-MySQL主从复制原理视频(老男孩出品)
查看>>
如何撰写优秀系统运维架构方案及推动实施案例分享
查看>>
Centos5.6 x86_64下安装DRBD+Heartbeat+NFS
查看>>
Cocos2d-x Eclipse下程序运行产生错误Effect initCheck() returned -1
查看>>
Lync Server 2010的部署系列(四) outlook无法加入联机会议
查看>>