精华内容
下载资源
问答
  • 动态代理与静态代理区别

    万次阅读 多人点赞 2018-09-18 09:26:55
    一、代理概念  为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托...

    一、代理概念 

    为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。 

    图1:代理模式 

    从图中可以看出,代理接口(Subject)、代理类(ProxySubject)、委托类(RealSubject)形成一个“品”字结构。

    根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种。 

    下面以一个模拟需求说明静态代理和动态代理:委托类要处理一项耗时较长的任务,客户类需要打印出执行任务消耗的时间。解决这个问题需要记录任务执行前时间和任务执行后时间,两个时间差就是任务执行消耗的时间。 

    二、静态代理 

    由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。 

    清单1:代理接口 

    /**  
     * 代理接口。处理给定名字的任务。 
     */  
    public interface Subject {  
      /** 
       * 执行给定名字的任务。 
        * @param taskName 任务名 
       */  
       public void dealTask(String taskName);   
    }  

    清单2:委托类,具体处理业务。

    /** 
     * 真正执行任务的类,实现了代理接口。 
     */  
    public class RealSubject implements Subject {  
      
     /** 
      * 执行给定名字的任务。这里打印出任务名,并休眠500ms模拟任务执行了很长时间 
      * @param taskName  
      */  
       @Override  
       public void dealTask(String taskName) {  
          System.out.println("正在执行任务:"+taskName);  
          try {  
             Thread.sleep(500);  
          } catch (InterruptedException e) {  
             e.printStackTrace();  
          }  
       }  
    }  

    清单3:静态代理类

    /** 
     * 代理类,实现了代理接口。 
     */  
    public class ProxySubject implements Subject {  
     //代理类持有一个委托类的对象引用  
     private Subject delegate;  
       
     public ProxySubject(Subject delegate) {  
      this.delegate = delegate;  
     }  
      
     /** 
      * 将请求分派给委托类执行,记录任务执行前后的时间,时间差即为任务的处理时间 
      *  
      * @param taskName 
      */  
     @Override  
     public void dealTask(String taskName) {  
      long stime = System.currentTimeMillis();   
      //将请求分派给委托类处理  
      delegate.dealTask(taskName);  
      long ftime = System.currentTimeMillis();   
      System.out.println("执行任务耗时"+(ftime - stime)+"毫秒");  
        
     }  
    } 

    清单4:生成静态代理类工厂

    public class SubjectStaticFactory {  
     //客户类调用此工厂方法获得代理对象。  
     //对客户类来说,其并不知道返回的是代理类对象还是委托类对象。  
     public static Subject getInstance(){   
      return new ProxySubject(new RealSubject());  
     }  
    }  

    清单5:客户类

    public class Client1 {  
      
     public static void main(String[] args) {  
      Subject proxy = SubjectStaticFactory.getInstance();  
      proxy.dealTask("DBQueryTask");  
     }   
      
    }  

    静态代理类优缺点 

    • 优点:
    1. 业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
    • 缺点:
    1. 代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。 
    2. 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。 

    三、动态代理 

    动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。 

    1、先看看与动态代理紧密关联的Java API

    1)java.lang.reflect.Proxy

    这是 Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。 

    清单6:Proxy类的静态方法

    // 方法 1: 该方法用于获取指定代理对象所关联的调用处理器  
    static InvocationHandler getInvocationHandler(Object proxy)   
      
    // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象  
    static Class getProxyClass(ClassLoader loader, Class[] interfaces)   
      
    // 方法 3:该方法用于判断指定类对象是否是一个动态代理类  
    static boolean isProxyClass(Class cl)   
      
    // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例  
    static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)   

    2)java.lang.reflect.InvocationHandler

    这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都要指定一个对应的调用处理器对象。 

    清单7:InvocationHandler的核心方法

    // 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象  
    // 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行  
    Object invoke(Object proxy, Method method, Object[] args)  

    3)java.lang.ClassLoader

    这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。 

    每次生成动态代理类对象时都需要指定一个类装载器对象

    2、动态代理实现步骤

    具体步骤是:

    1. 实现InvocationHandler接口创建自己的调用处理器
    2. 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
    3. 以调用处理器类型为参数,利用反射机制得到动态代理类的构造函数
    4. 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象

    清单8:分步骤实现动态代理 

    // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发  
    // 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用  
    InvocationHandler handler = new InvocationHandlerImpl(..);   
      
    // 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象  
    Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });   
      
    // 通过反射从生成的类对象获得构造函数对象  
    Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });   
      
    // 通过构造函数对象创建动态代理类实例  
    Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });  

    Proxy类的静态方法newProxyInstance对上面具体步骤的后三步做了封装,简化了动态代理对象的获取过程。

    清单9:简化后的动态代理实现 

    // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发  
    InvocationHandler handler = new InvocationHandlerImpl(..);   
      
    // 通过 Proxy 直接创建动态代理类实例  
    Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,   
         new Class[] { Interface.class },  handler );   

    3、动态代理实现示例 

    清单10:创建自己的调用处理器 

    /** 
     * 动态代理类对应的调用处理程序类 
     */  
    public class SubjectInvocationHandler implements InvocationHandler {  
       
     //代理类持有一个委托类的对象引用  
     private Object delegate;  
       
     public SubjectInvocationHandler(Object delegate) {  
      this.delegate = delegate;  
     }  
       
     @Override  
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
      long stime = System.currentTimeMillis();   
      //利用反射机制将请求分派给委托类处理。Method的invoke返回Object对象作为方法执行结果。  
      //因为示例程序没有返回值,所以这里忽略了返回值处理  
      method.invoke(delegate, args);  
      long ftime = System.currentTimeMillis();   
      System.out.println("执行任务耗时"+(ftime - stime)+"毫秒");  
        
      return null;  
     }  
    }   

    清单11:生成动态代理对象的工厂,工厂方法列出了如何生成动态代理类对象的步骤。

    /** 
     * 生成动态代理对象的工厂. 
     */  
    public class DynProxyFactory {  
     //客户类调用此工厂方法获得代理对象。  
     //对客户类来说,其并不知道返回的是代理类对象还是委托类对象。  
     public static Subject getInstance(){   
      Subject delegate = new RealSubject();  
      InvocationHandler handler = new SubjectInvocationHandler(delegate);  
      Subject proxy = null;  
      proxy = (Subject)Proxy.newProxyInstance(  
        delegate.getClass().getClassLoader(),   
        delegate.getClass().getInterfaces(),   
        handler);  
      return proxy;  
     }  
    }  

    清单12:动态代理客户类 

    public class Client {  
      
     public static void main(String[] args) {  
      
      Subject proxy = DynProxyFactory.getInstance();  
      proxy.dealTask("DBQueryTask");  
     }   
      
    }  

    4、动态代理机制特点

    首先是动态生成的代理类本身的一些特点。

    • 包:如果所代理的接口都是 public 的,那么它将被定义在顶层包(即包路径为空),如果所代理的接口中有非 public 的接口(因为接口不能被定义为 protect 或 private,所以除 public 之外就是默认的 package 访问级别),那么它将被定义在该接口所在包(假设代理了 com.ibm.developerworks 包中的某非 public 接口 A,那么新生成的代理类所在的包就是 com.ibm.developerworks),这样设计的目的是为了最大程度的保证动态代理类不会因为包管理的问题而无法被成功定义并访问;
    • 类修饰符:该代理类具有 final 和 public 修饰符,意味着它可以被所有的类访问,但是不能被再度继承;
    • 类名:格式是“$ProxyN”,其中 N 是一个逐一递增的阿拉伯数字,代表 Proxy 类第 N 次生成的动态代理类,值得注意的一点是,并不是每次调用 Proxy 的静态方法创建动态代理类都会使得 N 值增加,原因是如果对同一组接口(包括接口排列的顺序相同)试图重复创建动态代理类,它会很聪明地返回先前已经创建好的代理类的类对象,而不会再尝试去创建一个全新的代理类,这样可以节省不必要的代码重复生成,提高了代理类的创建效率。
    • 类继承关系:该类的继承关系如图: 

    图2:动态代理类的继承关系 

    由图可见,Proxy 类是它的父类,这个规则适用于所有由 Proxy 创建的动态代理类。而且该类还实现了其所代理的一组接口,这就是为什么它能够被安全地类型转换到其所代理的某接口的根本原因。 

    接下来让我们了解一下代理类实例的一些特点。每个实例都会关联一个调用处理器对象,可以通过 Proxy 提供的静态方法 getInvocationHandler 去获得代理类实例的调用处理器对象。在代理类实例上调用其代理的接口中所声明的方法时,这些方法最终都会由调用处理器的 invoke 方法执行,此外,值得注意的是,代理类的根类 java.lang.Object 中有三个方法也同样会被分派到调用处理器的 invoke 方法执行,它们是 hashCode,equals 和 toString,可能的原因有:一是因为这些方法为 public 且非 final 类型,能够被代理类覆盖;二是因为这些方法往往呈现出一个类的某种特征属性,具有一定的区分度,所以为了保证代理类与委托类对外的一致性,这三个方法也应该被分派到委托类执行。当代理的一组接口有重复声明的方法且该方法被调用时,代理类总是从排在最前面的接口中获取方法对象并分派给调用处理器,而无论代理类实例是否正在以该接口(或继承于该接口的某子接口)的形式被外部引用,因为在代理类内部无法区分其当前的被引用类型。 

    接着来了解一下被代理的一组接口有哪些特点。首先,要注意不能有重复的接口,以避免动态代理类代码生成时的编译错误。其次,这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败。再次,需被代理的所有非 public 的接口必须在同一个包中,否则代理类生成也会失败。最后,接口的数目不能超过 65535,这是 JVM 设定的限制。 

    最后再来了解一下异常处理方面的特点。从调用处理器接口声明的方法中可以看到理论上它能够抛出任何类型的异常,因为所有的异常都继承于 Throwable 接口,但事实是否如此呢?答案是否定的,原因是我们必须遵守一个继承原则:即子类覆盖父类或实现父接口的方法时,抛出的异常必须在原方法支持的异常列表之内。所以虽然调用处理器理论上讲能够,但实际上往往受限制,除非父接口中的方法支持抛 Throwable 异常。那么如果在 invoke 方法中的确产生了接口方法声明中不支持的异常,那将如何呢?放心,Java 动态代理类已经为我们设计好了解决方法:它将会抛出 UndeclaredThrowableException 异常。这个异常是一个 RuntimeException 类型,所以不会引起编译错误。通过该异常的 getCause 方法,还可以获得原来那个不受支持的异常对象,以便于错误诊断。 

    5、动态代理的优点和美中不足 

    • 优点:动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。在本示例中看不出来,因为invoke方法体内嵌入了具体的外围业务(记录任务处理前后时间并计算时间差),实际中可以类似Spring AOP那样配置外围业务。 
    • 缺点:诚然,Proxy 已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。 

    有很多条理由,人们可以否定对 class 代理的必要性,但是同样有一些理由,相信支持 class 动态代理会更美好。接口和类的划分,本就不是很明显,只是到了 Java 中才变得如此的细化。如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个小小的遗憾。

     原文链接:动态代理与静态代理区别

    展开全文
  • 动态代理与静态代理区别

    千次阅读 2014-04-10 20:21:24
    JAVA的静态代理与动态代理比较  一、概念 代理模式是常用的Java 设计模式,它的特征是代理类委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理...


    JAVA的静态代理与动态代理比较 
    一、概念
    代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。

    静态代理类:
    由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。

    二、静态代理类
    如下, HelloServiceProxy 类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl 类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl 对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。

    由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。

    例程1 HelloService.java
    package proxy;
    import java.util.Date;
    public interface HelloService{
    public String echo(String msg);
    public Date getTime();
    }
    例程2 HelloServiceImpl.java
    package proxy;
    import java.util.Date;
    public class HelloServiceImpl implements HelloService{
    public String echo(String msg){
    return "echo:"+msg;
    }
    public Date getTime(){
    return new Date();
    }
    }
    例程3 HelloServiceProxy.java
    package proxy;
    import java.util.Date;
    public class HelloServiceProxy implements HelloService{
    private HelloService helloService; //表示被代理的HelloService 实例
    public HelloServiceProxy(HelloService helloService){
    this.helloService=helloService;
    }
    public void setHelloServiceProxy(HelloService helloService){
    this.helloService=helloService;
    }
    public String echo(String msg){
    System.out.println("before calling echo()"); //预处理
    String result=helloService.echo(msg); //调用被代理的HelloService 实例的echo()方法
    System.out.println("after calling echo()"); //事后处理
    return result;
    }
    public Date getTime(){
    System.out.println("before calling getTime()"); //预处理
    Date date=helloService.getTime(); //调用被代理的HelloService 实例的getTime()方法
    System.out.println("after calling getTime()"); //事后处理
    return date;
    }
    }
    在Client1 类的main()方法中,先创建了一个HelloServiceImpl对象,又创建了一个HelloServiceProxy对象,最后调用HelloServiceProxy对象的echo()方法。
    例程4 Client1.java
    package proxy;
    public class Client1{
    public static void main(String args[]){
    HelloService helloService=new HelloServiceImpl();
    HelloService helloServiceProxy=new HelloServiceProxy(helloService);
    System.out.println(helloServiceProxy.echo("hello"));
    }
    }
    运行Client1 类,打印结果如下:
    before calling echo()
    after calling echo()
    echo:hello
    例程3 的HelloServiceProxy 类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。

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

    Proxy类提供了创建动态代理类及其实例的静态方法。
    (1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下:

    public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException

    参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。

    (2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下:

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws 
    IllegalArgumentException

    参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口,参数handler 指定与动态代理类关联的 InvocationHandler 对象。

    以下两种方式都创建了实现Foo接口的动态代理类的实例:
    /**** 方式一 ****/
    //创建InvocationHandler对象
    InvocationHandler handler = new MyInvocationHandler(...);

    //创建动态代理类
    Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });

    //创建动态代理类的实例
    Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
    newInstance(new Object[] { handler });

    /**** 方式二 ****/
    //创建InvocationHandler对象
    InvocationHandler handler = new MyInvocationHandler(...);

    //直接创建动态代理类的实例
    Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);

    由Proxy类的静态方法创建的动态代理类具有以下特点:
    动态代理类是public、final和非抽象类型的;
    动态代理类继承了java.lang.reflect.Proxy类;
    动态代理类的名字以“$Proxy”开头;
    动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;

    Proxy 类的isProxyClass(Class<?> cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类;

    动态代理类都具有一个public 类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。

    由Proxy类的静态方法创建的动态代理类的实例具有以下特点:
    1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:
    (Foo) foo //合法

    2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。

    3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。

    InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:
    Object invoke(Object proxy,Method method,Object[] args) throws Throwable

    参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args 指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。

    四、最后看一个实例:
    HelloServiceProxyFactory 类的getHelloServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。

    例程5 HelloServiceProxyFactory.java
    package proxy;
    import java.lang.reflect.*;
    public class HelloServiceProxyFactory {
    /** 创建一个实现了HelloService 接口的动态代理类的实例
    * 参数helloService 引用被代理的HelloService 实例
    */
    public static HelloService getHelloServiceProxy(final HelloService helloService){
    //创建一个实现了InvocationHandler接口的匿名类的实例
    InvocationHandler handler=new InvocationHandler(){
    public Object invoke(Object proxy,Method method,Object args[])throws Exception{
    System.out.println("before calling "+method); //预处理
    Object result=method.invoke(helloService,args);
    //调用被代理的HelloService 实例的方法
    System.out.println("after calling "+method); //事后处理
    return result;
    }
    };
    Class classType=HelloService.class;
    return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(),
    new Class[]{classType},
    handler);
    }
    }
    如下所示的Client2 类先创建了一个HelloServiceImpl 实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。
    例程6 Client2.java
    package proxy;
    public class Client2{
    public static void main(String args[]){
    HelloService helloService=new HelloServiceImpl();
    HelloService helloServiceProxy=HelloServiceProxyFactory.getHelloServiceProxy(helloService);
    System.out.println("动态代理类的名字为"+helloServiceProxy.getClass().getName());
    System.out.println(helloServiceProxy.echo("Hello"));
    }
    }
    运行Client2,打印结果如下:
    动态代理类的名字为$Proxy0
    before calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
    after calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
    echo:Hello
    从结果看出,动态代理类的名字为$Proxy0。
    评论(3)|100

    yh114long |来自团队java开发 |五级采纳率30%
    擅长:编程语言足球大连市
    按默认排序|按时间排序
    其他1条回答
    2011-07-08 14:12MySelf_Beyond|四级
    楼上说的太多了,没看。动态代理直接看多态的资料。
    我只简单是说一下:
    比如你继承了一个类或一个接口。
    在你重写了父类的方法后,那么当你声明了一个父类引用指向子类对象的实例时
    这个实例调用重写的方法时就会自动的绑定为子类的方法。

    例:public class A{
    public void a1(){
    System.out.println("父A");
    }
    }

    class B extends A{
    public void a1(){
    System.out.println("子B");
    }

    }

    class C{
    public static void main(String arg[]){
    A a = new B();
    a.a1();
    }
    }

    输出结果就是 子B

    展开全文
  • 代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问...为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效...

    代理Proxy:

    Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题

    代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
    在这里插入图片描述
    为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。

    更通俗的说,代理解决的问题当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理,但是切记,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。

    使用场合举例:

    如果需要委托类处理某一业务,那么我们就可以先在代理类中统一处理然后在调用具体实现类

    按照代理的创建时期,代理类可以分为两种:

    静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。

    动态:在程序运行时运用反射机制动态创建而成。

    下面分别用静态代理与动态代理演示一个示例:

    添加打印日志的功能,即每个方法调用之前和调用之后写入日志

    静态代理:

    具体用户管理实现类

    public class UserManagerImpl implements UserManager {
     
    	@Override
    	public void addUser(String userId, String userName) {
    		System.out.println("UserManagerImpl.addUser");
    	}
     
    	@Override
    	public void delUser(String userId) {
    		System.out.println("UserManagerImpl.delUser");
    	}
     
    	@Override
    	public String findUser(String userId) {
    		System.out.println("UserManagerImpl.findUser");
    		return "张三";
    	}
     
    	@Override
    	public void modifyUser(String userId, String userName) {
    		System.out.println("UserManagerImpl.modifyUser");
     
    	}
    }
    
    

    代理类–代理用户管理实现类

    public class UserManagerImplProxy implements UserManager {
     
    	// 目标对象
    	private UserManager userManager;
    	// 通过构造方法传入目标对象
    	public UserManagerImplProxy(UserManager userManager){
    		this.userManager=userManager;
    	}
    	@Override
    	public void addUser(String userId, String userName) {
    		try{
    				//添加打印日志的功能
    				//开始添加用户
    				System.out.println("start-->addUser()");
    				userManager.addUser(userId, userName);
    				//添加用户成功
    				System.out.println("success-->addUser()");
    			}catch(Exception e){
    				//添加用户失败
    				System.out.println("error-->addUser()");
    			}
    	}
     
    	@Override
    	public void delUser(String userId) {
    		userManager.delUser(userId);
    	}
     
    	@Override
    	public String findUser(String userId) {
    		userManager.findUser(userId);
    		return "张三";
    	}
     
    	@Override
    	public void modifyUser(String userId, String userName) {
    		userManager.modifyUser(userId,userName);
    	}
     
    }
    
    

    客户端调用

    public class Client {
     
    	public static void main(String[] args){
    		//UserManager userManager=new UserManagerImpl();
    		UserManager userManager=new UserManagerImplProxy(new UserManagerImpl());
    		userManager.addUser("1111", "张三");
    	}
    }
    
    

    静态代理类优缺点

    优点:

    代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合),对于如上的客户端代码,newUserManagerImpl()可以应用工厂将它隐藏,如上只是举个例子而已。

    缺点:

    1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
    2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。如上的代码是只为UserManager类的访问提供了代理,但是如果还要为其他类如Department类提供代理的话,就需要我们再次添加代理Department的代理类。

    举例说明:代理可以对实现类进行统一的管理,如在调用具体实现类之前,需要打印日志等信息,这样我们只需要添加一个代理类,在代理类中添加打印日志的功能,然后调用实现类,这样就避免了修改具体实现类。满足我们所说的开闭原则。但是如果想让每个实现类都添加打印日志的功能的话,就需要添加多个代理类,以及代理类中各个方法都需要添加打印日志功能(如上的代理方法中删除,修改,以及查询都需要添加上打印日志的功能)

    即静态代理类只能为特定的接口(Service)服务。如想要为多个接口服务则需要建立很多个代理类。

    引入动态代理:

    根据如上的介绍,你会发现每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类

    所以我们就会想办法可以通过一个代理类完成全部的代理功能,那么我们就需要用动态代理

    在上面的示例中,一个代理只能代理一种类型,而且是在编译器就已经确定被代理的对象。而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象

    在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持

    java.lang.reflect.InvocationHandler接口的定义如下:

    //Object proxy:被代理的对象
    //Method method:要调用的方法
    //Object[] args:方法调用时所需要参数
    public interface InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    }
    
    

    java.lang.reflect.Proxy类的定义如下:

    //CLassLoader loader:类的加载器
    //Class<?> interfaces:得到全部的接口
    //InvocationHandler h:得到InvocationHandler接口的子类的实例
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
    
    

    动态代理:

    具体实现类

    public class UserManagerImpl implements UserManager {
     
    	@Override
    	public void addUser(String userId, String userName) {
    		System.out.println("UserManagerImpl.addUser");
    	}
     
    	@Override
    	public void delUser(String userId) {
    		System.out.println("UserManagerImpl.delUser");
    	}
     
    	@Override
    	public String findUser(String userId) {
    		System.out.println("UserManagerImpl.findUser");
    		return "张三";
    	}
     
    	@Override
    	public void modifyUser(String userId, String userName) {
    		System.out.println("UserManagerImpl.modifyUser");
     
    	}
     
    }
    
    

    动态创建代理对象的类

    //动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类
       
    public class LogHandler implements InvocationHandler {
     
    	// 目标对象
    	private Object targetObject;
    	//绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。            
    	public Object newProxyInstance(Object targetObject){
    		this.targetObject=targetObject;
    		//该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例  
    		//第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
    		//第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
    		//第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
    		//根据传入的目标返回一个代理对象
    		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
    				targetObject.getClass().getInterfaces(),this);
    	}
    	@Override
    	//关联的这个实现类的方法被调用时将被执行
    	/*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		System.out.println("start-->>");
    		for(int i=0;i<args.length;i++){
    			System.out.println(args[i]);
    		}
    		Object ret=null;
    		try{
    			/*原对象方法调用前处理日志信息*/
    			System.out.println("satrt-->>");
    			
    			//调用目标方法
    			ret=method.invoke(targetObject, args);
    			/*原对象方法调用后处理日志信息*/
    			System.out.println("success-->>");
    		}catch(Exception e){
    			e.printStackTrace();
    			System.out.println("error-->>");
    			throw e;
    		}
    		return ret;
    	}
     
    }
    
    

    被代理对象targetObject通过参数传递进来,我们通过targetObject.getClass().getClassLoader()获取ClassLoader对象,然后通过targetObject.getClass().getInterfaces()获取它实现的所有接口,然后将targetObject包装到实现了InvocationHandler接口的LogHandler对象中。通过newProxyInstance函数我们就获得了一个动态代理对象。

    public class Client {
     
    	public static void main(String[] args){
    		LogHandler logHandler=new LogHandler();
    		UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());
    		//UserManager userManager=new UserManagerImpl();
    		userManager.addUser("1111", "张三");
    	}
    }
    
    

    可以看到,我们可以通过LogHandler代理不同类型的对象,如果我们把对外的接口都通过动态代理来实现,那么所有的函数调用最终都会经过invoke函数的转发,因此我们就可以在这里做一些自己想做的操作,比如日志系统、事务、拦截器、权限控制等。这也就是AOP(面向切面编程)的基本原理。

    插曲:

    AOP(AspectOrientedProgramming):将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码—解耦。

    针对如上的示例解释:
    我们来看上面的UserManagerImplProxy类,它的两个方法System.out.println("start-->addUser()")和System.out.println("success-->addUser()"),这是做核心动作之前和之后的两个截取段,正是这两个截取段,却是我们AOP的基础,在OOP里,System.out.println("start-->addUser()")、核心动作、System.out.println("success-->addUser()")这个三个动作在多个类里始终在一起,但他们所要完成的逻辑却是不同的,如System.out.println("start-->addUser()")里做的可能是权限的判断,在所有类中它都是做权限判断,而在每个类里核心动作却各不相同,System.out.println("success-->addUser()")可能做的是日志,在所有类里它都做日志。正是因为在所有的类里,核心代码之前的操作和核心代码之后的操作都做的是同样的逻辑,因此我们需要将它们提取出来,单独分析,设计和编码,这就是我们的AOP思想。一句话说,AOP只是在对OOP的基础上进行进一步抽象,使我们的类的职责更加单一。

    动态代理优点:

    动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强

    总结:

    其实所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。

    代理对象就是把被代理对象包装一层,在其内部做一些额外的工作,比如用户需要上facebook,而普通网络无法直接访问,网络代理帮助用户先翻墙,然后再访问facebook。这就是代理的作用了。

    纵观静态代理与动态代理,它们都能实现相同的功能,而我们看从静态代理到动态代理的这个过程,我们会发现其实动态代理只是对类做了进一步抽象和封装,使其复用性和易用性得到进一步提升而这不仅仅符合了面向对象的设计理念,其中还有AOP的身影,这也提供给我们对类抽象的一种参考。关于动态代理与AOP的关系,个人觉得AOP是一种思想,而动态代理是一种AOP思想的实现!

    展开全文
  • JAVA的静态代理与动态代理比较 一、概念 代理模式是常用的Java 设计模式,它的特征是代理类委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类...
    JAVA的静态代理与动态代理比较 
    一、概念
        代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。
    
    静态代理类:
         由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。
    
    二、静态代理类
         如下, HelloServiceProxy 类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl 类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl 对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。
    
    由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。
    
    例程1 HelloService.java
    package proxy;
    import java.util.Date;
    public interface HelloService{
       public String echo(String msg);
       public Date getTime();
    }
    例程2 HelloServiceImpl.java
    package proxy;
    import java.util.Date;
    public class HelloServiceImpl implements HelloService{
       public String echo(String msg){
         return "echo:"+msg;
       }
       public Date getTime(){
        return new Date();
       }
    }
    例程3 HelloServiceProxy.java
    package proxy;
    import java.util.Date;
    public class HelloServiceProxy implements HelloService{
       private HelloService helloService; //表示被代理的HelloService 实例
       public HelloServiceProxy(HelloService helloService){
         this.helloService=helloService;
       }
       public void setHelloServiceProxy(HelloService helloService){
          this.helloService=helloService;
       }
       public String echo(String msg){
         System.out.println("before calling echo()"); //预处理
         String result=helloService.echo(msg); //调用被代理的HelloService 实例的echo()方法
         System.out.println("after calling echo()"); //事后处理
         return result;
       }
       public Date getTime(){
         System.out.println("before calling getTime()"); //预处理
         Date date=helloService.getTime(); //调用被代理的HelloService 实例的getTime()方法
         System.out.println("after calling getTime()"); //事后处理
         return date;
        }
    }
       在Client1 类的main()方法中,先创建了一个HelloServiceImpl对象,又创建了一个HelloServiceProxy对象,最后调用HelloServiceProxy对象的echo()方法。
    例程4 Client1.java
    package proxy;
    public class Client1{
       public static void main(String args[]){
        HelloService helloService=new HelloServiceImpl();
        HelloService helloServiceProxy=new HelloServiceProxy(helloService);
        System.out.println(helloServiceProxy.echo("hello"));
       }
    }
    运行Client1 类,打印结果如下:
    before calling echo()
    after calling echo()
    echo:hello
    例程3 的HelloServiceProxy 类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。
    
    三、动态代理类
          与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
    
    Proxy类提供了创建动态代理类及其实例的静态方法。
    (1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下:
    
    public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException
    
       参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。
    
    (2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下:
    
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws 
          IllegalArgumentException
    
        参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口,参数handler 指定与动态代理类关联的 InvocationHandler 对象。
    
    以下两种方式都创建了实现Foo接口的动态代理类的实例:
    /**** 方式一 ****/
    //创建InvocationHandler对象
    InvocationHandler handler = new MyInvocationHandler(...);
    
    //创建动态代理类
    Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
    
    //创建动态代理类的实例
    Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
        newInstance(new Object[] { handler });
    
    /**** 方式二 ****/
    //创建InvocationHandler对象
    InvocationHandler handler = new MyInvocationHandler(...);
    
    //直接创建动态代理类的实例
    Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);
    
    由Proxy类的静态方法创建的动态代理类具有以下特点:
       动态代理类是public、final和非抽象类型的;
       动态代理类继承了java.lang.reflect.Proxy类;
       动态代理类的名字以“$Proxy”开头;
       动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;
    
    Proxy 类的isProxyClass(Class<?> cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类;
    
    动态代理类都具有一个public 类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。
    
    由Proxy类的静态方法创建的动态代理类的实例具有以下特点:
    1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:
    (Foo) foo //合法
    
    2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。
    
    3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。
    
    InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:
    Object invoke(Object proxy,Method method,Object[] args) throws Throwable
    
    参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args 指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。
    
    四、最后看一个实例:
         HelloServiceProxyFactory 类的getHelloServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。
    
    例程5 HelloServiceProxyFactory.java
    package proxy;
    import java.lang.reflect.*;
    public class HelloServiceProxyFactory {
       /** 创建一个实现了HelloService 接口的动态代理类的实例
        * 参数helloService 引用被代理的HelloService 实例
        */
       public static HelloService getHelloServiceProxy(final HelloService helloService){
       //创建一个实现了InvocationHandler接口的匿名类的实例
       InvocationHandler handler=new InvocationHandler(){
          public Object invoke(Object proxy,Method method,Object args[])throws Exception{
            System.out.println("before calling "+method); //预处理
            Object result=method.invoke(helloService,args);
           //调用被代理的HelloService 实例的方法
            System.out.println("after calling "+method); //事后处理
            return result;
           }
         };
        Class classType=HelloService.class;
        return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(),
            new Class[]{classType},
            handler);
        }
    }
    如下所示的Client2 类先创建了一个HelloServiceImpl 实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。
    例程6 Client2.java
    package proxy;
    public class Client2{
       public static void main(String args[]){
        HelloService helloService=new HelloServiceImpl();
        HelloService helloServiceProxy=HelloServiceProxyFactory.getHelloServiceProxy(helloService);
        System.out.println("动态代理类的名字为"+helloServiceProxy.getClass().getName());
        System.out.println(helloServiceProxy.echo("Hello"));
       }
    }
    运行Client2,打印结果如下:
    动态代理类的名字为$Proxy0
    before calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
    after calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
    echo:Hello
    从结果看出,动态代理类的名字为$Proxy0。
    展开全文
  • 动态代理静态代理到底有什么区别,好处在哪里?
  • 动态代理静态代理区别

    千次阅读 2017-04-25 10:18:06
    一、概念  代理模式是常用的Java设计模式,它的特征是代理类委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类委托类之间通常会...静态代理
  • AOP是Aspect Oriented Programing的简称,面向切面编程。AOP适合于那些具有横切逻辑的...AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理动态代理两大类,其中静态代理是指使用 AOP 框
  • 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存  在了,故内存中的Class对象是由JVM加载class文件生成的。 动态代理类:在程序运行时,运用反射机制...
  • CGLIB动态代理 是可以针对接口普通类(继承方式),底层使用ASM框架生成字节码完成代理功能 我在网上查资料说AspectJ是静态代理 在编译期间就生成了class文件完成了代理。这点容易理解一种编译的技术。 那么我...
  • 代理模式:由被代理对象(业务类)和代理类组成,代理类通常包括日志代理类、权限代理类。 代理源代码分析,转载此篇博客: ... 静态代理 ...被代理对象和代理类都确定时可以...动态代理 被代理对象多,代理类多的情...
  • 静态代理动态代理区别 静态代理:代理类有源码,经过javac编译加载使用。 动态代理:代理类没有源码,动态生成代理类的字节码文件,接着利用字节码文件生成Class对象,接着利用反射生成代理实例对象,所以...
  • 反射技术中有两个很重要的部分,一个是注解,一个是动态代理,刚刚学完代理模式,做一个笔记记录一下~ 什么是代理模式呢,生活中最常见的代理模式应该就是房租中介了吧, 房地产商提供房源,中介顾客接触,而房...
  • 动态代理可以用来实现AOP编程,好处不言而喻。 那么什么是静态代理呢? 今天看了一下,貌似是说让程序眼自己去写proxy类,要代理的类实现相同的接口,然后proxy调用方法的时候,实际上内部自己手动调用被代理类...
  • 一、概念 &amp;nbsp;代理模式是常用的Java设计模式,它的特征是代理类委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。...静态代理类...
  • 代理CGLIB 动态代理 AspectJ静态代理区别   1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表;而动态代理则以 spring AOP 为代表 1 1.2. JDK动态代理是模拟接口实现的方式...
  • 文章目录一、简介1、代理分类:2、代码区别:二、静态代理1、接口定义要做的事情2、具体用户实现类3、代理类(业务增强类)4、测试类三、动态代理1、JDK动态代理类1.1、有接口有委托类的情况1.2、仅有接口的情况2、...
  • 静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类 静态代理事先知道要代理什么东西,而动态代理不知道要代理什么,只有在运行的时候才知道,动态代理是实现JDK里的InvocationHandler接口的 invoke...
  • java静态代理与动态代理区别

    千次阅读 2015-10-25 22:15:22
    java静态代理动态代理 本文动态代理部分内容大量引自:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/  一、代理概念  为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有...
  • 网上有很多讲动态代理静态代理的写法作为区分原因,但是都没有讲到本质上 本文主要从应用层自上而下看待这个问题 应用场景 静态代理 // 数据准备 Order order = new Order();order.setUserId(1); Money money =...
  • 静态代理与动态代理

    千次阅读 热门讨论 2016-07-28 10:17:28
    静态代理  23种设计模式中,代理模式是一种很经典的模式,当我们想改变一个类的行为的时候(比如添加额外的服务像添加日志等),可以创造一个跟这个类实现相同接口的类,重写对应的方法。这就相当于为一个类创建...
  • 静态代理与动态代理(JDK、CGLIB) 问题引入 什么是静态代理? 什么是动态代理静态代理动态代理区别是什么? JDK动态代理和CGLIB动态代理区别静态代理 主要是通过代码的业务来处理,在编译...
  • 1. 使用原因 最最最主要的原因就是,在不改变目标对象方法的情况下对...动态代理静态代理区别在于有没有重新加载内存,为什么这么说呢,可以从实现中可以看出,静态代理是通过实现同一接口,在执行目标对象方...
  • 代理也分静态代理动态代理,我们先以简单的静态代理为例子。静态代理:定义一个接口package designmode.代理模式;public interface Sourceable { public void method(); }被代理的对象,它实现了 Sourceable ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 76,277
精华内容 30,510
关键字:

动态代理与静态代理的区别