黑马程序员--代理

-----------ASP.Net+Unity开发----.Net培训------------------

代理类
程序中的代理:要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理、日志、计算方法的运行时间、事务管理、等等。


代理类要调用目标类的功能。

目标类  doSomeThing(){
        业务功能代码
            }
代理类  doSomeThing(){
          //前置系统功能代码
           目标对象.doSomeThing()
          //后置系统功能代码   
         }

动态代理的工作原理:


1)Client(客户端)调用代理,代理的构造方法接受一个InvocationHandler,client调用代理的各个方法,代理的各个方法请求转发给刚才通过构造方法传入的handler对象,又把各请求分发给目标的相应的方法。就是将handler封装起来,其中this引用了当前的放(发来什么请求就接受哪个方法)。
猜想分析动态生成的类的内部代码:
1、动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和一个如下接受InvocationHandler参数的构造方法。
2、构造方法接受一个InvocationHandler对象,接受对象了要干什么用呢?该方法内部的代码会是怎样的呢?
实现Collection接口的动态类中的各个方法的代码又是怎样的呢?InvocationHandler接口中定义的invoke方法接受的三个参数又是什么意思?图解说明如下:

分析为什么动态类的实例对象的getClass()方法返回了正确结果呢?
为何动态类的实例对象的getClass()方法返回了正确结果,而没调用invoke方法:
因为代理类从Object上继承了许多方法,其中只对三个方法(hashCode、equals和toString)进行开发,委托给handler去自行处理,对于它身上其他方法不会交给代理类去实现,所以对于getClass()方法,还是由Object本身实现的。即proxy3.getClass(),该是什么结果还是什么结果,并不会交给invoke方法处理。

自定义代理类的步骤:
方式1:
             获得动态代理类的字节码文件
		Class claz=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		//通过反射获得该动态代理类的构造方法
		Constructor c=claz.getConstructor(InvocationHandler.class);
	     //编写一个InvocationHandler类
		class myInvocationHandler implements InvocationHandler{

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
			
		}
		//创建实例,接受一个invocationhandler对象
		c.newInstance(new myInvocationHandler());

方式2,newProxyInstance这个方法需要三个参数,可以直接创建target的代理对象  
        Object proxy3 = Proxy.newProxyInstance(  
                target.getClass().getClassLoader(),  
                /*new Class[]{Collection.class},*/  
                  
                //获取target上的接口  
                target.getClass().getInterfaces(),  
                new InvocationHandler(){  
                  
                    public Object invoke(Object proxy, Method method, Object[] args)  
                            throws Throwable {  
  
                        /*long beginTime = System.currentTimeMillis();  
                        Object retVal = method.invoke(target, args);  
                        long endTime = System.currentTimeMillis();  
                        System.out.println(method.getName() + " running time of " + (endTime - beginTime));  
                        return retVal;*/  
                          
                        //把上边的代码封装到一个类中,让后调用该类的方法,就实现了方法的封装  
                        advice.beforeMethod(method);  
                        Object retVal = method.invoke(target, args);  
                        advice.afterMethod(method);  
                        return retVal;                        
                          
                    }  
                }  
                );  
        return proxy3;  
    }  
  
}  



-----------ASP.Net+Unity开发----.Net培训------------------

详情请查看http://www.itheima.com


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值