java技术-静态代理到动态代理

代理模式的本质:通过增加一定的间接性来完成某些附加的操作。

 

比如我们通过某个代理来给mm送礼物:

public class testproxy{

         publicstatic void main(String args[])

         {

                   schoolgirlmm = new schoolgirl("jiaojiao");

                   proxypx = new proxy(mm);

                  

                   px.giveFlower();

                   px.giveDoll();

                   px.givePic();

         }

}

可观察到在测试主体代码中,并不存在谁送礼物给mm的信息;实际的信息隐藏在proxy中的具体某对象。

class proxy implements igive{

        

         Persuitpm;

        

         publicproxy(schoolgirl mm){

                   pm= new Persuit(mm);

         }

        

         publicvoid giveFlower(){

                   pm.giveFlower();

         }

        

         publicvoid givePic(){

                   pm.givePic();

         }

        

         publicvoid giveDoll(){

                   pm.giveDoll();

         }

}

总体上感觉是绕了下。全部的源代码见src1文件夹。

 


 

根据已有的文献资料:

http://blog.youkuaiyun.com/zsx923/article/details/5205138

代理可分为:静态代理和动态代理,那毫无疑问,上述的内容只是静态代理。静态代理的缺点也很明显:每代理一个对象,就需要创建一个新的代理类。

 

克服静态代理的缺点,动态代理的优点在于:不需要创建代理类。但又能享受代理类的优点。主要依靠java提供proxy代理类来支持。

 

下面按照如下文档的叙述:

http://langyu.iteye.com/blog/410071

该文档中的相关资料显示:

1.       首先要根据我们的具体类来创建InvocationHandler对象 ;

2.       然后再根据1中创建的handler对象,再与新生成的代理类相关联;

3.       关联完成后,即可以调用。

 

现在还不想深入其中的细节,但本质上觉得只是把生成代理类的事情,api来自动完成了。具体的测试源代码见src2。

 

要彻底理解java动态代理,看如下的文档:

http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html

 

http://blog.youkuaiyun.com/sunmenggmail/article/details/8545554

 

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Objectinvoke(Objectobj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request()args为该方法的参数数组。这个抽象方法在代理类中动态实现。

 

(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandlerh)
:构造函数,估计用于给内部的h赋值。StaticClass getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

 

Static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)

 

形象的来讲,就是通过Proxy.newProxyInstance生成一个代理类的对象,然后,对这个对象的所有方法的调用,都会自动的调用invoke函数,对原有函数的追踪或是统计开销,都可以在invoke函数中实现。在使用动态代理类时,我们必须实现InvocationHandler接口。

 

下面来写个实例,验证对于代理对象的任何方法的调用,最终都会触发invoke函数;开始之前,想想必要的关键点:

1.     要继承的那个接口的名字:InvocationHandler;

2.  Invoke方法的原型:public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  

3.           return method.invoke(proxied, args);  

4.   }  

4.      创建代理类的基本语法:Proxy.newProxyInstance(Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandle(real));  

掌握上述的基本技术点后,再来我们的实验,从用例入手:

假设被代理的类中拥有两个方法:

actFirst();

actSecond();

然后生成代理类后,比如生成的代理类是:daili

daili.actFirst();

daili.actSecond();

查看上述两者的调用路径是如何的?

 

拥有上述信息后,如何完成相关的设计?

 

Public interfaceService{

         Public void doFirst;

         Public void doSecond;

}

 

Public MyServcieimplements Service{

         Public void doFirst(){

                   System.out.println(“I am thefirst”)

         }

 

         Public void doSecond(){

                   System.out.println(“I am thesecond”);

         }

}

 

定义自己的InvocationHandler:

Public class MyHandlerimplements InvocationHandler{

    //invoke方法的原型:

    Public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{

       return method.invoke(myservice, args);

    }

}

 

下面开始测试动态代理的主类:

publicclass myproxy{

        

         //首先创建我们的service类,然后再以该类为模板创建代理类?

         MyService ms = new MyService();

        

         Object daili = proxy.newProxyInstance(Service.class.getClassLoader(), new Class[]{Service.class}, new MyHandle()); 

         Daili.doFirst();

         Daili.doSecond();

}

 

 

实现过程中遇到的问题:

1.      居然连interface中的方法该怎么定义都不确定;

方法的定义只要到”()”即可,不需要有”{”;

 

importjava.lang.reflect.*;

 

interfaceService{

         public void doFirst();

         public void doSecond();

}

 

classMyService implements Service{

 

         public void doFirst(){

                   System.out.println("I amthe first");

         }

 

         public void doSecond(){

                  System.out.println("Iam the second");

         }

}

 

//定义自己的InvocationHandler:

classMyHandler implements InvocationHandler{

         //invoke方法的原型:

        

         private MyService myservice;

        

         public MyHandler(MyService ms){

                   myservice = ms;

         }

        

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

                   if(method.getName().equals("doSecond"))

                            returnmethod.invoke(myservice, args);  //方法需要来自某个特定的类;

                   return null;

         }

}

 

//下面开始测试动态代理的主类:

publicclass myproxy{

        

         public static void main(String args[])

         {

                   //首先创建我们的service类,然后再以该类为模板创建代理类?

                   MyService ms = newMyService();

                  

                   Service daili =(Service)Proxy.newProxyInstance

                   (Service.class.getClassLoader(),new Class[]{Service.class}, new MyHandler(ms));

                  

                   daili.doFirst();

                   daili.doSecond();

         }

}

 

如上的实例代码,无论daili调用什么方法,MyHandler中的invoke方法都会被调用;

通过这么绕一圈,增加代码执行过程中的间接性,可以在此中间性中做很多的处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值