黑马程序员--动态代理

---------------------- android培训java培训、期待与您交流! ----------------------

动态代理

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

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

       CGLIB库可以动态生成一个类的子类,一个雷的子类也可以用作该类的代理,所以,如果为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB

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

1.      在调用目标的方法之前

2.      在调用目标的方法之后

3.      在调用目标方法前后

4.      在除了目标方法异常的catch块中

         Constructor[]constructors = clazzProxy.getConstructors();//获取构造方法


                  
for (Constructorconstructor : constructors) {// 遍历构造方法
                           
String name =constructor.getName();// 构造方法名字
                           
StringBuildersBuilder = new StringBuilder(name);
                            sBuilder.append('(');
                            Class[]clazzParams = constructor.getParameterTypes();//获取构造方法的参数列表
                           
for (ClassclazzParam : clazzParams) {// 遍历参数列表
                                    
sBuilder.append(clazzParam.getName()).append(',');//获取参数名
                           
}
                            if(clazzParams != null || clazzParams.length == 0)
                                     sBuilder.deleteCharAt(sBuilder.length()- 1);
                            sBuilder.append(')');
                            System.out.println(sBuilder.toString());
                   }


                   System.out.println("------------beginmethods list");
                   Method[] methods =clazzProxy.getMethods();// 获取方法


                  
for (Method method :methods) {// 遍历方法
                           
String name =method.getName();// 获取方法名
                           
StringBuildersBuilder = new StringBuilder(name);
                            sBuilder.append('(');
                            Class[]clazzParams = method.getParameterTypes();// 获取方法的参数列表
                           
for (ClassclazzParam : clazzParams) {
                                     sBuilder.append(clazzParam.getName()).append(',');//获取参数名
                           
}
                            if(clazzParams != null && clazzParams.length != 0)
                                     sBuilder.deleteCharAt(sBuilder.length()- 1);
                            sBuilder.append(')');
                            System.out.println(sBuilder.toString());
                   }


                   // 创建实例对象
                  
System.out.println("------------beginmethods list");
                   //clazzProxy.newInstance();
                   classMyInvocationHandler implements InvocationHandler {


                            @Override
                            public Objectinvoke(Object arg0, Method arg1, Object[] arg2)
                                               throwsThrowable {
                                     returnnull;
                            }


                   }
                   Constructor constructor= clazzProxy
                                     .getConstructor(InvocationHandler.class);
                   //创建动态类的三种方法
                  
Collection proxy1 =(Collection)constructor.newInstance(new MyInvocationHandler());
                   System.out.println(proxy1);//toString 返回了null 如果是null会报空指针异常
                  
proxy1.clear();
//                 proxy1.size();//调用有返回值的方法时,会出现空指针异常
                  
//原因分析,调用invoke时返回的是null,而该方法要求返回一个整数,无法将null转成整数所以报错
                  

                   Collection proxy2 =(Collection)constructor.newInstance(new InvocationHandler(){
                            @Override
                            public Objectinvoke(Object proxy, Method method, Object[] args)
                                               throwsThrowable {
                                     returnnull;
                            }
                   });//使用匿名内部类
                  
System.out.println(proxy2); 
                   Collection proxy3 =(Collection)Proxy.newProxyInstance(
                                     Collection.class.getClassLoader(),//定义代理类的类加载器
                                    
newClass[]{Collection.class},//代理类要实现的接口列表
                                    
newInvocationHandler(){//指派方法调用的调用处理程序 
                                              
ArrayListtarget = new ArrayList();
                                               publicObject invoke(Object proxy, //调用方法的代理实例
                                                                
Methodmethod,//对应于在代理实例上调用的接口方法的 Method实例
                                                                
Object[]args//包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null
                                                                
)throws Throwable {
                                                        longbeginTime = System.currentTimeMillis();
                                                        ObjectretVal = method.invoke(target, args);
                                                        longendTime = System.currentTimeMillis();
                                                        System.out.println("runtime:" + (time =endTime - beginTime+1));//有没有办法将 (endTime - beginTime)返回去??
                                                       
returnretVal;
                                               }
                                     });
                   proxy3.add("zxx");//调动三次add,却打印四次runtime: 0??
                  
proxy3.add("bxd");
                   proxy3.add("lhm");//原来每调用一次方法都会执行InvocationHandler中的invoke方法
                  
System.out.println(proxy3.size());//调用三次addSystem.out.println()中调用一次size,所以是四次

---------------------- android培训java培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net/heima

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值