`
cvics_ailk
  • 浏览: 10778 次
社区版块
存档分类
最新评论

JDK代理和CGLIB代理的区别

    博客分类:
  • Java
 
阅读更多

一.概念

        代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道。如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法。如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱。所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户。而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品。

专业点说:代理模式是常用的java设计模式,代理模式给某一个对象提供代理,并由代理对象控制原对象(目标对象,被代理对象)的引用。简单点说,就是通过一个工厂生成一个类的代理对象,当客户端使用的时候不直接使用目标对象,而是直接使用代理对象。

二.jdk的静态代理

       首先看一下静态代理: 
        /**
          * 定义一个账户接口
          */ 
         public interface Count { 
            // 查看账户方法 
           public void queryCount(); 
           // 修改账户方法 
           public void updateCount(); 
         }
        /**
          * 目标对象(包含业务逻辑)
          */ 
 public class CountImpl implements Count { 
     @Override 
     public void queryCount() { 
         System.out.println("查看账户方法..."); 
     } 
     @Override 
     public void updateCount() { 
         System.out.println("修改账户方法..."); 
     } 
 }
为目标对象创建代理对象:CountProxy.java代理对象持有目标对象的引用。
 /**
  * 这是一个代理类(增强CountImpl实现类)
  */ 
 public class CountProxy implements Count { 
     private CountImpl countImpl; 
     /**
      * 覆盖默认构造器
      */ 
     public CountProxy(CountImpl countImpl) { 
         this.countImpl = countImpl; 
     } 
     @Override 
     public void queryCount() { 
         System.out.println("事务处理之前"); 
         // 调用委托类的方法; 
         countImpl.queryCount(); 
         System.out.println("事务处理之后"); 
     } 
     @Override 
     public void updateCount() { 
         System.out.println("事务处理之前"); 
         // 调用委托类的方法; 
         countImpl.updateCount(); 
         System.out.println("事务处理之后"); 
     } 
 } 
TestCount.java
 /**
   * 测试Count类
   */ 
 public class TestCount { 
     public static void main(String[] args) { 
         CountProxy countProxy = new CountProxy(new CountImpl()); 
         countProxy.updateCount(); 
         countProxy.queryCount(); 
     } 
 }

        用法:

               1、目标对象和代理对象都要实现相同的接口。

               2、代理对象持有目标对象的引用。

        缺点

               1、需要建大量的代理类。

               2、违背了重复代码只写一次的原则。

一.jdk动态代理

       与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

       Jdk的动态要求目标对象必须实现接口,因为它创建代理对象的时候是根据接口创建的。如果不实现接口,jdk无法给目标对象创建代理对象。被代理对象可以可以实现多个接口,创建代理时指定创建某个接口的代理对象就可以调用该接口定义的方法了。是Spring AOP代理的默认方式。

动态代理示例:     

1、定义一个接口

public interface BookFacade { 
    public void addBook(); 
}

2、接口实现类

 public class BookFacadeImpl implements BookFacade { 
    @Override 
    public void addBook() { 
        System.out.println("增加图书方法。。。"); 
     } 
 }

3、提供一个生成代理对象的的类

 /**
   * JDK动态代理代理类
   */ 
  public class BookFacadeProxy implements InvocationHandler { 
      private Object target; 
      /**
       * 绑定委托对象并返回一个代理类
       */ 
      public Object newInstance(Object target) { 
          this.target = target; 
          //取得代理对象 
          return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                  target.getClass().getInterfaces(), this);   //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷) 
      } 
      @Override 
      public Object invoke(Object proxy, Method method, Object[] args) 
              throws Throwable { 
          Object result=null; 
          System.out.println("事物开始"); 
          //执行方法 
          result=method.invoke(target, args); 
          System.out.println("事物结束"); 
          return result; 
      } 
  }

4、TestProxy.java

 public class TestProxy { 
    public static void main(String[] args) { 
         BookFacadeProxy proxy = new BookFacadeProxy(); 
         BookFacade bookProxy = (BookFacade) proxy.newInstance(new BookFacadeImpl()); 
         bookProxy.addBook(); 
     } 
 }

 

但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib

动态代理了。

二.cglib 动态代理

        jdk给目标类提供动态要求目标类必须实现接口,当一个目标类不实现接口时,jdk是无法为其提供动态代理的。cglib 却能给这样的类提供动态代理。Spring在给某个类提供动态代理时会自动在jdk动态代理和cglib动态代理中动态的选择。

使用cglib为目标类提供动态代理:需要导入cglib.jar和asm.jar

如果出现asm中的类无法找到的异常,在java工程中是真的缺少asm.jar,而在web工程中很可能是asm.jar和spring提供的org.springframework.asm-3.0.4.RELEASE.jar包冲突。

       cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。
因为是继承,所以该类或方法最好不要声明成final

示例:

1、定义一个接口

public interface BookFacade {
     public void addBook();
}

2、接口实现类

public class BookFacadeImpl implements BookFacade {
      @Override
      public void addBook() {
            System.out.println("增加图书方法。。。");
      }
}

3、创建一个代理工厂,用于生成目标类的代理对象

/**
  * 使用cglib动态代理
  * 
  * @author student
  * 
  */ 
 public class BookFacadeCglib implements MethodInterceptor { 
     private Object target; 
  
     /**
      * 创建代理对象
      * 
      * @param target
      * @return
      */ 
     public Object getInstance(Object target) { 
         this.target = target; 
         Enhancer enhancer = new Enhancer(); 
         enhancer.setSuperclass(this.target.getClass()); 
         // 回调方法 
         enhancer.setCallback(this); 
         // 创建代理对象 
         return enhancer.create(); 
     } 
  
     @Override 
     // 回调方法 
     public Object intercept(Object obj, Method method, Object[] args, 
             MethodProxy proxy) throws Throwable { 
         System.out.println("事物开始"); 
         proxy.invokeSuper(obj, args); 
         System.out.println("事物结束"); 
         return null;  
   }  
 } 

4、TestCglib.java

 public class TestCglib { 
     public static void main(String[] args) { 
         BookFacadeCglib cglib=new BookFacadeCglib(); 
         BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1()); 
         bookCglib.addBook(); 
     } 
  }

总结:CGLib所创建的动态代理对象的性能比JDK的高大概10倍,但CGLib在创建代理对象的时间比JDK大概多8倍,所以对于singleton的代理对象或者具有实例池的代理,因为无需重复的创建代理对象,所以比较适合CGLib动态代理技术,反之选择JDK代理。值得一提的是由于CGLib采用动态创建子类的方式生成代理对象,所以不能对目标类中final的方法进行代理。

分享到:
评论

相关推荐

    JDK代理和Cglib代理

    JDK代理和Cglib代理是两种常用的动态代理实现方式。 **JDK代理(Java Dynamic Proxy)** JDK动态代理是Java标准库提供的一种代理机制,位于`java.lang.reflect`包下的`Proxy`类和`InvocationHandler`接口。JDK代理...

    浅谈JDK动态代理与CGLIB代理去区别

    本篇文章将深入探讨JDK动态代理和CGLIB代理的区别,以及它们在实际应用中的选择。 首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象...

    java代理机制 JDK动态代理和cglib代理 详解

    本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始...

    Spring框架中JDK动态代理和cglib动态代理

    Spring 框架中 JDK 动态代理和 CGLIB 动态代理是 Spring AOP 中一个非常重要的知识点。Spring AOP 框架会根据实际情况选择使用 JDK 的动态代理还是 CGLIB 的动态代理。 JDK 动态代理是 Java 自带的动态代理机制,它...

    JDK动态代理和CGLIB代理

    JDK动态代理和CGLIB代理是两种常用的实现方式。 首先,我们来看看JDK动态代理。JDK动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象...

    java 动态代理实例(JDK代理与CGLIB代理)

    动态代理主要分为两种:JDK代理和CGLIB代理。 **JDK代理**是基于接口的代理,它通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。当我们的目标对象实现了特定的接口时,我们可以...

    Jdk动态代理和cglib动态代理原理

    - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成的子类,而JDK代理需要反射调用接口方法。 在实际开发中,如Spring AOP框架就同时支持JDK和...

    Java JDK代理、CGLIB、AspectJ代理分析比较

    接下来将详细介绍三种常用的Java代理技术:JDK代理、CGLIB代理以及AspectJ代理,并对比它们各自的优缺点。 #### 二、静态代理实例 静态代理可以通过下面的例子进行说明: ```java public interface Calculator { ...

    jdk与cglib动态度代理的区别原理

    本文将深入探讨这两种技术的区别和原理。 **JDK动态代理**: JDK动态代理是Java标准库提供的一种代理机制,位于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口中。它基于接口来实现,...

    jdk 的动态代理和CGLIB代理

    jdk 的动态代理和CGLIB代理

    AOP之JDK动态代理和CGLib动态代理

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    jdk动态代理 cglib3.0动态代理

    JDK代理基于接口,适用于简单场景;CGLIB通过字节码技术,适用于更复杂的需求。开发者可以根据项目需求选择合适的方法。对于学习和理解这两种动态代理机制,可以参考提供的博客链接,以及深入研究源码,这将有助于...

    jdk动态代理和CGlib动态代理

    JDK动态代理和CGlib动态代理是Java中实现这一目标的两种主要方式。 ### JDK动态代理 JDK动态代理基于Java的接口实现。如果一个类实现了至少一个接口,我们就可以为这个类创建一个动态代理。动态代理通过`java.lang....

    JDK动态代理和Cglib动态代理实例源码

    - **灵活性**:JDK代理要求目标类实现接口,而Cglib无此限制。 - **使用场景**:如果目标类已经实现了接口,且不关心性能,优先选择JDK代理;否则,Cglib是更好的选择。 在`DynamicProxyTest`源码中,我们可以看到...

    java动态代理实例(jdk动态代理和cglib)

    以下是一个简单的CGLIB代理示例: ```java import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxyExample ...

    java动态代理(JDK和cglib).pdf

    动态代理主要分为两种实现方式:JDK动态代理和CGLIB动态代理。 1. JDK动态代理: JDK动态代理基于Java的反射API,它要求被代理的目标对象必须实现一个或多个接口。JDK动态代理的核心类是`java.lang.reflect.Proxy`...

    JDK和CGlib分别实现的动态代理源代码

    两者在性能上,CGlib通常比JDK代理稍快,但创建代理的过程相对复杂。选择哪种代理方式取决于具体的需求和项目情况。了解并掌握这两种动态代理技术,能够使你在处理AOP(面向切面编程)等高级编程需求时游刃有余。

    jdk和cglib动态代理的例子{jar包+源码}

    jdk和cglib动态代理的例子{jar包+源码} 解压:如有问题 用快压

    JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)

    Java提供了两种主要的动态代理实现方式:JDK动态代理和CGLIB动态代理。 **JDK动态代理**: JDK动态代理基于接口实现,也就是说,被代理的对象必须实现至少一个接口。代理机制的核心是`java.lang.reflect.Proxy`类和...

    Jdk动态代理,cglib动态代理,反射和拦截器(链)示例

    Java中的动态代理、反射和...总之,理解和掌握JDK动态代理、CGLIB动态代理、反射和拦截器是提升Java开发技能的关键步骤。通过实际操作这些示例,你将能够更好地应用这些技术到实际项目中,提高代码的灵活性和可维护性。

Global site tag (gtag.js) - Google Analytics