新用户注册 | 会员登录
登录 极速注册
取消
热门标签 | HotTags
当前位置:   开发笔记 > 编程语言 > 正文

黑马程序员—张老师基础加强7-动态代理

代理:要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。例如:异常处理,日志和计算方法的运行时间,事物管理等,怎么做如在运行前后增加计算时间的方法

代理:

    要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。

    例如:异常处理,日志和计算方法的运行时间,事物管理等,怎么做

    如 在运行前后增加计算时间的方法。show(){

       sop();

    }

    编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

动态代理:

    要为系统中的各种接口的类增加代理功能,那需要太多代理类。

    jvm可以在运行期间动态生成出类的字节码,这种动态生成的类往往被调用作代理类,

    即动态代理类。

    jvm生成动态类必须实现一个或多个接口,所以,jvm生成的动态类只能作为相同接口的目标类的代理。

    如果目标类没有接口,CGLIB库(不是jvm提供的)可以动态生成一个类的子类,一个类的子类,也可以用作该类的代理,所以,如果目标类没有接口,可以使用CGLIB

    代理类除了调用目标的相应方法和返回目标的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:

    1.在调用目标方法之前

    2.在调用目标方法之后

    3.在调用目标方法前后

    4.在处理目标方法异常的catch块中。

Proxy类:Proxy 提供用于创建动态代理类和实例的静态方法

方法全是静态:

常用方法:

static Class getProxyClass(ClassLoader loader, Class... interfaces)

static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

 练习:获取代理类Proxy的构造器和方法

//1.--------------创建Collection动态类,打印代理类的所有方法。
    //创建代理类,传递的是类加载和代理实现的接口!!!
    Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
    System.out.println(clazzProxy1.getName());//$Proxy0,代理类名
    //获取构造方法,打印如$proxy0()  $proxy0(String str,int i) 
    Constructor[] cOnstructors= clazzProxy1.getConstructors();    
    for(Constructor cons:constructors){
        String name = cons.getName();
        StringBuilder stringbuilder = new StringBuilder(name);
        stringbuilder.append("(");
        //添加参数
        Class[] types = cons.getParameterTypes();//返回的是 Class  [] getParameterTypes()  
        for(Class cl:types){
            stringbuilder.append(cl.getName()+",");
        }
        if(types!=null&&types.length!=0)
        {
            //将最后一组参数的","去掉。前提构造函数有参数
        stringbuilder.deleteCharAt(stringbuilder.length()-1);
        }        
        stringbuilder.append(")");
        System.out.println(    stringbuilder.toString());
    }    
    Method[] methods = clazzProxy1.getMethods();
      for(Method met:methods){
        StringBuilder sb = new StringBuilder(met.getName());
        sb.append("(");
        Class[] methodcls = met.getParameterTypes();//注意
        for(Class cls:methodcls){
            sb.append(cls.getName()+",");//注意
        }
        if(methodcls.length!=0&&methodcls!=null){
             sb.deleteCharAt(sb.length()-1);//stringbuilder无法索引最后一次出现字符的位置,只能是字符串。lastindexof
        }
        sb.append(")");
        System.out.println(sb);
    }        


练习:创建代理对象

//2.-------------------------------创建实例对象
    //注意newInstence是调用无参构造函数,clazzProxy1没有 怎么办
    Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
    Constructor constructor1 = clazzProxy1.getConstructor(InvocationHandler.class);//构造函数需要参数区分
//1.0 InvocationHandler是接口,只能new其子类。接口在子类必须覆盖父类的方法。
    class myInvocationHandle1 implements InvocationHandler{              
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
             return null;
        }
    }
//1.1直接用匿名内部类的方式
    Collection colls2 = (Collection) constructor1.newInstance(new InvocationHandler(){     
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable { 
            return null;
        }        
    });  
    //创建的对象是什么类型???动态类必须实现一个或多个接口,返回的是collection
    Collection colls1 = (Collection)constructor1.newInstance(new myInvocationHandle1());//获得构造方法参数是参数类型InvocationHandler.class,创建对象时真正的参数InvocationHandler对象。
    System.out.println(colls1);//打印结果是null,说明colls1的返回值是null,不是对象本身是null,否则报空指针。
    System.out.println(colls1.toString());
    colls1.clear();
    //colls1.size();//包空指针异常    
    /*     
    Proxy的构造方法接受了InvocationHandler对象,到底要干什么?     
    当然是要在某个时候要用到。那什么时候用?
    看代理中的add()方法。add中内部大概是:
    add(){
    InvotationHandler.invoke(this,this.getClass.getMethod("add"),null)
    }
    InvotationHandler类:是代理实例调”用程序处理“的接口,当调用代理的方法时,会将方法进行编码并将任务指派的invoke()方法中。
    invoke(Object proxy, Method method, Object[] args):因为代理同和代理的类实现了相同的接口,所有调用代理的方法时,就将
    任务指派invoke方法中。
    总结:调用代理的x方法,就去调用handler中invoke方法。而invoker有可以通过反射来调用目标中的x方法。
    invoke中三个参数是:调用的哪个代理对象,调用代理对象的哪个方法,调用代理方法中的参数。代理三要素。谁,买,电脑,然后到总部提货。
    */

练习:一步到位法创建代理对象 但这是硬编码

API文档例子;一步到位的方法。
    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
           new Class[] { Foo.class },
           handler);
    Collection colls3 = (Collection) Proxy.newProxyInstance(loader,
            interfaces,//不能是可变参数,因为可变参数必须放在最后,只能用数组
            handler
            );
    //1.2一步到位创建Collection的动态类。动态类是collection类型。
    Collection colls3 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),
            new Class[]{Collection.class},  //注意:可能会有多个接口,本例子只有一个。
            new InvocationHandler(){                      
            public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {            
            long start  = System.currentTimeMillis();
            //挂到目标上。怎么挂:加到invoke方法中,谁是目标:ArrayList。
            ArrayList dest = new ArrayList();
            Object retval= method.invoke(dest, args);//调用代理传过来的方法。
            long end = System.currentTimeMillis();
            System.out.println(method.getName()+"运行时间"+(end-start));//(end-start)注意加括号
            return retval;
          
        }        
        }
            );
    //add()方法的结果,就是Invoke返回的retval.这也是为什么第一次,调用size()时,会报错。因为第一次调用时返回的是null;
    colls3.add("biixnagdong");//去找Handler的invoke方法, 放在局部,每次add()的目标不一致。
    colls3.add("binagdong");
    colls3.add("binagdong");
    //调用代理的方法时,
    System.out.println(colls3.size());//没有空指针了,,结果为0.
  注:我们计算时间的方法是硬添加进来的,以后不可能只给一个用户。可以将用户目标的方法封装成对象,并作为参数传递进去。去调用代理中的管理方法。
  那么在编框架是,就变成了四要素。要传两个对象:用户目标的程序封装的对象和要修改的系统功能的方法封装的对象。 

练习:将系统功能和目标作为参数传递,获取动态代理,不再是硬编码

ArrayList arrayproxy = new ArrayList();
    //对象的类型是Collection,和目标ArrayList无关
    Collection proxy = (Collection)getProxy(arrayproxy, new myAdvice());
    proxy.add("sdf");
    proxy.add("sdf");
    proxy.add("sdf");
    proxy.size();    

//将目标和系统功能作为参数传递(接口多态) 获取Collection的动态代理
    public static Object getProxy(final Object target,final advice adv){//多态,内部类调用要final
        //一步到位发,获取代理对象
        Object proxyobj =  Proxy.newProxyInstance(target.getClass().getClassLoader(),
                 target.getClass().getInterfaces(),
                 new InvocationHandler(){
                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        //挂上系统功能的代码
                            adv.beforeRun();
                            Object obj =method.invoke(target, args);//将目标传递进来。
                            adv.afterRun();
                            return obj;
                         
                    }});
        return proxyobj;        
    }    
}//获取时间的接口 系统功能 一般有四个方法。
interface advice{
    public void beforeRun();
    public void afterRun();
}
class myAdvice implements advice{
    private long start;
    private long end;
    @Override
    public void beforeRun() {
        System.out.println("开始运行!");
         start= System.currentTimeMillis();
    }
    @Override
    public void afterRun() {
        System.out.println("运行结束");
         end= System.currentTimeMillis();    
         System.out.println(end-start);
    }    
}

 

练习:写一个代理框架

代理框架:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyDemo2 {
    /**创建代理类
     * loader - 定义代理类的类加载器
        interfaces - 代理类要实现的接口列表
        h - 指派方法调用的调用处理程序
         应用:做代理框架,将目标对象和功能代码对象传入.     
     * @param args
     */
    public static void main(String[] args) {
        Server server= new Server();
        ProxyTools proxytools = new ProxyTools();
        ProxyInte ServerProxy = (ProxyInte) getProxy(server,proxytools);//实现的接口是什么类型,对象就是什么类型
     ServerProxy.show();

    }
    public static Object getProxy(final Object target,final Tools tool){//将客户和代理的管理工具传入
        //创建Server的代理类,并调用获取时间的管理办法.
        //1.使用静态方法
        Object obj = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),//注意是谁的class文件
                target.getClass().getInterfaces(),//注意接口是谁
                new InvocationHandler(){
                    @Override
                    public Object invoke(Object proxy, Method method,
                    Object[] args) throws Throwable {//invoke方法该写什么???
                     //挂上系统功能的代码
                        tool.beforeRun();
                        Object retval = method.invoke(target, args);//重要,使用反射将客户的对象传入,运行代理传入的代码
                        tool.afterRun();
                        return retval;
                    }
                    
                });
         
            return obj;
    }

}
//创建目标客户
class Server implements ProxyInte{
    @Override
    public void show() {
        // TODO Auto-generated method stub
        System.out.println("客户运行的代码");
    }    
}
//定义获取运行时间的代理管理方法
interface Tools{//接口定义规则
    void beforeRun();
    void afterRun();
}
class ProxyTools implements Tools{
    long start;
    long end;
    public void beforeRun(){
         start = System.currentTimeMillis();        
    }
    public void afterRun(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {             
            e.printStackTrace();
        }
         end  = System.currentTimeMillis();         
        System.out.println("耗时:"+(end-start));
    }
}
//目标类和代理类共同的接口
interface ProxyInte{
    public void show();
}


    

 

 

 

 


  • 程序员
  • 日志
  • jvm
  • static
  • get
  • ssl
  • int
  • object
  • instance
推荐阅读
  • go

    在类中定义数组时出错 - Error on defining arrays in class

    Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • list

    关于cuowu类的错误提示和使用AdjustmentListener的问题

    本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • jsp

    java 线程死锁模拟

    1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • jsp

    Java太阳系小游戏分析和源码详解

    Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • utf-8

    开发笔记:加密&json&StringIO模块&BytesIO模块

    开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • list

    Java容器中的compareto方法排序原理解析

    Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • ip

    SpringBoot yml 配置 多配置文件,开发环境,生产环境配置文件分开

    原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • jsp

    Hibernate基础映射

    在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • jsp

    Spring特性实现接口多类的动态调用详解

    Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • utf-8

    XML介绍与使用的概述及标签规则

    XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • utf-8

    Java高并发程序设计学习-线程安全的概念与synchronized

    本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • list

    org.apache.catalina.LifecycleEvent类的使用及代码示例

    标题: ... [详细]
  • dll

    Android源码深入理解JNI技术的概述和应用

    Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • list

    关于Linq to sql 实现 模糊查询 string数组

    前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • list

    iOS数据库Sqlite的SQL语句分类和常见约束关键字

    本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
author-avatar
手机用户2502883383
这个家伙很懒,什么也没留下!
Tags | 热门标签
  • php7
  • chat
  • audio
  • post
  • actionscrip
  • future
  • hashset
  • web
  • ip
  • format
  • copy
  • vba
  • dagger
  • jsp
  • install
  • vbscript
  • callback
  • fetch
  • md5
  • require
  • replace
  • export
  • go
  • list
  • flutter
  • dll
  • utf-8
  • config
  • tree
  • hashcode
RankList | 热门文章
  • 1 如何从PHP扩展克隆对象 - How to clone an object from PHP extension
  • 2 springSecurity前后端分离集成jwt(4)
  • 3 使用node.js压缩流优化http请求
  • 4 使用 json 模块,使json数据格式与Python字典dict数据格式互相转换,获取数据更加方便
  • 5 C语言12单链表01基本功能实现
  • 6 Emoji表情2020年更新上线:总计达117个
  • 7 调出人物照片的清爽淡黄色
  • 8 Allegro中如何进行尺寸标注
  • 9 同步_同步条件
  • 10 【CTF攻略】2017年陕西省网络空间安全技术大赛过关攻略
  • 11 POJ 1442 (Treap 板子记录)
  • 12 android 高德地图sha1,Android调试高德SDK,如何获取SHA1?
  • 13 AoCoder 1983 [AGC001E] BBQ Hard(组合数+dp)
  • 14 如何在不编写平台特定代码的情况下将页面从任何匿名页面A切换到已知页面B
  • 15 返璞归真系列|解读 Polygon 最新进展与竞争态势
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 | PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有
     

PHP网站源码爱联模板制作观澜至尊标王石岩网站排名优化南澳百姓网标王推广大芬关键词按天计费大芬优秀网站设计大运关键词按天收费东莞模板推广横岗百度网站优化木棉湾关键词排名永湖网站优化推广福永网页设计惠州企业网站建设木棉湾关键词排名包年推广双龙百度爱采购南澳seo同乐SEO按天计费同乐seo优化民治网站制作南山网站定制龙华网站制作龙岗模板推广大芬网站建设丹竹头建站宝安网站开发石岩关键词排名包年推广爱联标王大运网络营销广州网页制作丹竹头企业网站设计歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

PHP网站源码 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化