java 静态代理、JDK代理、Cglib代理

1 、代理模式
    代理对象代表目标对象被访问,代理类 可以在目标对象实现的基础上, 增强额外的功能操作 ,即扩展目标对象的功能。
      

2、 常见的三种代理实现
  • 静态代理
  • 动态代理
    • java JDK代理
    • Cglib代理

3、 静态代理
  • 代理类和被代理类实现相同的接口或继承相同的父类,代理对象通过他们的共同的接口或父类访问被代理类。
  • 实现:下面是问手机(YourPhone)的价格,但实际上是问华为手机的价格。
//公共接口:手机
    publicinterface Phone{
         publicvoid price();
    }
    
    //被代理类:华为
    classHuaWei implements Phone{
         @Override
         publicvoid price() {
             System.out.println("1000RMB");
         }
    }
    
    //代理类
    classYourPhone implements Phone{
         HuaWeiphone;    //必须要有被代理类的对象
         
         publicYourPhone(HuaWei phone){
             this.phone=phone;
         }
         
         @Override
         publicvoid price() {
             phone.price(); //实际是访问被代理类的价格
         }
    }
    
    //测试代理
    publicvoid testProxy(){
         Phonep=newYourPhone(newHuaWei());   //代理对象
         p.price(); //访问代理类的价格
    }


  • 优点:可以看到:在YourPhone类的price函数里加上其他功能,如:敬语。即添加额外功能。
  • 缺点:每一个类都应要有一个代理类,即类数量增多了。接口一旦要更改,其实现类也需要更改。

4、java JDK动态代理
  • 特点:代理类不需要实现共同接口或继承共同父类,直接通过JDK的API生成代理对象。
  • 要动态创建代理对象需要用到InvocationHandler这个接口
    //公共接口:手机
    publicinterface Phone{
         publicvoid price();
    }
    
    //被代理类:华为
    classHuaWei implements Phone{
         @Override
         publicvoid price() {
             System.out.println("1000RMB");
         }
    }
    
    /*编写一个动态代理,不需实现接口,但需要制定接口。
     * 值得注意的是,这可以代理不同的被代理类了*/
    classProxyFactory{
         Objectphone;    //被代理类对象,不应指定某个代理类,让其动态绑定
         
         publicProxyFactory(Object phone) {
             this.phone=phone;
         }
         
         //h获取代理对象
         publicObject getProxyInstance() {
             //创建被代理类的事务处理器
             InvocationHandlerih=newInvocationHandler() {
                 @Override
                 publicObject invoke(Object proxy, Methodmethod, Object[]args)throws Throwable {
                     returnmethod.invoke(phone,args);
                 }
             };
             /*
              * phone.getClass().getClassLoader():被代理类的类加载器
              * phone.getClass().getInterfaces():被代理类的接口
              */
             returnProxy.newProxyInstance(phone.getClass().getClassLoader(),phone.getClass().getInterfaces(),ih);
         }
    }
    
    //测试动态代理
    publicvoid testProxy(){
         Phonep=newHuaWei();//指定具体代理类
         PhoneDProxy=(Phone)newProxyFactory(p).getProxyInstance();        //创建动态代理对象
         DProxy.price();  
    }



5、 动态代理与静态代理的区别
  • 上面说过,动态代理不用创建每一个代理类。即对于2个被代理类,静态代理需要创建2个代理类,而动态代理只需创建另一个动态代理对象即可。
  • 下面增加apple手机的类,高亮的为新增代码
    • 静态代理类:必须创建代理类Apple
         //公共接口:手机
          public interface Phone{
              public void price();
         }
         
          //被代理类:华为
          class HuaWei implements Phone{
              @Override
              public void price() {
                 System. out .println( "1000RMB" );
             }
         }
         
          //被代理类:苹果
          class Apple implements Phone{
              @Override
              public void price() {
                 System. out .println( "5000RMB" );
             }
         }
         
          //代理类HuaWei
          class YourPhone implements Phone{
             HuaWei phone ;     //必须要有被代理类的对象
             
              public YourPhone(HuaWei phone ){
                  this . phone = phone ;
             }
             
              @Override
              public void price() {
                  phone .price();  //实际是访问被代理类的价格
             }
         }
         
           //代理类apple
          class YourPhone2 implements Phone{
             Apple phone //必须要有被代理类的对象
             
              public YourPhone2(Apple phone ){
                  this . phone = phone ;
             }
             
              @Override
              public void price() {
                  phone .price();  //实际是访问被代理类的价格
             }
         }
         
          //测试静态代理
          public void testProxy2(){
             Phone p = new YourPhone( new HuaWei());     //代理对象
              Phone p2 = new YourPhone2( new Apple());
              p .price();  //访问代理类的价格
               p2 .price();
         }

  • 动态代理类:只需创建另一个代理对象
        //公共接口:手机
          public interface Phone{
              public void price();
         }
         
          //被代理类:华为
          class HuaWei implements Phone{
              @Override
              public void price() {
                 System. out .println( "1000RMB" );
             }
         }
         
           //被代理类:苹果
          class Apple implements Phone{
              @Override
              public void price() {
                 System. out .println( "5000RMB" );
             }
         }
         
          /*编写一个动态代理,不需实现接口,但需要制定接口。
          * 值得注意的是,这可以代理不同的被代理类了*/
          class ProxyFactory{
             Object phone ;     //被代理类对象,不应指定某个代理类,让其动态绑定
             
              public ProxyFactory(Object phone ) {
                  this . phone = phone ;
             }
             
              //h获取代理对象
              public Object getProxyInstance() {
                  //创建被代理类的事务处理器
                 InvocationHandler ih = new InvocationHandler() {
                      @Override
                      public Object invoke(Object proxy , Method method , Object[] args ) throws Throwable {
                           return method .invoke( phone , args );
                     }
                 };
                  /*
                  * phone.getClass().getClassLoader():被代理类的类加载器
                  * phone.getClass().getInterfaces():被代理类的接口
                  */
                  return Proxy. newProxyInstance ( phone .getClass().getClassLoader(), phone .getClass().getInterfaces(), ih );
             }
         }
         
          //测试动态代理
          public void testProxy(){
             Phone p = new HuaWei(); //指定具体被代理类
             Phone DProxy =(Phone) new ProxyFactory( p ).getProxyInstance();         //创建动态代理对象
              DProxy .price();  
              Phone p2 = new Apple();
             Phone DProxy2 =(Phone) new ProxyFactory( p2 ).getProxyInstance();
              DProxy2 .price();
         }



6、 Cglib代理
  • Cglib代理也是动态代理,其与JDK代理不同的地方在于:JDK的被代理类需实现接口,而Cglib代理的被代理类不需实现接口。Cglib以被代理类的子类对象作为其代理类。
  • 需下载底层包:Cglib-nodep 或其核心包Cglib-core
    • 将下载的jar包导入项目:右键项目——Properties——Java Build Path,选Libraries选卡项,点击Add External JARs...。选择包导入后确认即可
  • Cglib包的底层是通过使用一个字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
  • 被代理的类不能为final,否则报错
  • 被代理对象的方法如果为final/static,那么就不会被拦截,而是直接执行该方法.
    //被代理类(需要注意的是,该类不能是内部类)
    publicclass HuaWei {
        publicvoid price() {
             System.out.println(this+"1000RMB");
        }
    }
    //另起一类
    publicclass Cglib {
         
    //Cglib代理
    classProxyFactory2 implements MethodInterceptor{
         Objectphone;
         
         publicProxyFactory2(Object phone) {
             this.phone=phone;
         }
         
         publicObject getProxyInstance() {
             Enhancerenhance=newEnhancer();  //工具类
             enhance.setSuperclass(phone.getClass());   //设置父类:被代理类
             enhance.setCallback(this);    //设置回调函数,这里的this是函数所在的类
             //返回创建的子类:代理对象
             returnenhance.create();
         }
         
         /**
          * 执行被代理类的方法时拦截,并执行该方法
          *@param
          * obj:被代理类的对象
          * method:被代理类的方法反射对象
          * args:方法参数
          * proxy:代理类对象
          */
         @Override
         publicObject intercept(Object obj, Methodmethod, Object[]args, MethodProxyproxy)throws Throwable {
             returnmethod.invoke(phone,args);
             //写法2
//           proxy.invokeSuper(obj,args);
//           return null;

         }
    }
    
    //测试Cglib代理
    publicvoid testProxy3() {
         HuaWeihw=newHuaWei();
         HuaWeiproxy=(HuaWei)newProxyFactory2(hw).getProxyInstance();
         proxy.price();
    }
         
    publicstatic void main(String[] args) {
         //TODO Auto-generated method stub
         Cglibc=newCglib();
         c.testProxy3();
    }
}


  • 程序分析:从testProxy3()函数开始,生成HuaWei类对象,这里我踩了一下坑:先前把这个类设置为内部类(原因不知道是什么,估计要看源码,望告知)。然后生成ProxyFactory2对象,主要是为了执行get类的getProxyInstance()方法,从而得到被代理类的子类:代理对象
  • 该代理对象执行被代理类的方法时,都会被intercept 方法拦截(为了得到被代理对象)。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值