`
m635674608
  • 浏览: 5028869 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

为什么动态代理只能基于接口?

 
阅读更多

动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

代理类具用以下属性:

代理类是公共的、最终的,而不是抽象的。
未指定代理类的非限定名称。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留。
代理类扩展 java.lang.reflect.Proxy。
代理类会按同一顺序准确地实现其创建时指定的接口。
如果代理类实现了非公共接口,那么它将在与该接口相同的包中定义。否则,代理类的包也是未指定的。注意,包密封将不阻止代理类在运行时在特定包中的成功定义,也不会阻止相同类加载器和带有特定签名的包所定义的类。
由于代理类将实现所有在其创建时指定的接口,所以对其 Class 对象调用 getInterfaces 将返回一个包含相同接口列表的数组(按其创建时指定的顺序),对其 Class 对象调用 getMethods 将返回一个包括这些接口中所有方法的 Method 对象的数组,并且调用 getMethod 将会在代理接口中找到期望的一些方法。
如果 Proxy.isProxyClass 方法传递代理类(由 Proxy.getProxyClass 返回的类,或由 Proxy.newProxyInstance 返回的对象的类),则该方法返回 true,否则返回 false。
代理类的 java.security.ProtectionDomain 与由引导类加载器(如 java.lang.Object)加载的系统类相同,原因是代理类的代码由受信任的系统代码生成。此保护域通常被授予 java.security.AllPermission。
每个代理类都有一个可以带一个参数(接口 InvocationHandler 的实现)的公共构造方法,用于设置代理实例的调用处理程序。并非必须使用反射 API 才能访问公共构造方法,通过调用 Proxy.newInstance 方法(将调用 Proxy.getProxyClass 的操作和调用带有调用处理程序的构造方法结合在一起)也可以创建代理实例。
代理实例具有以下属性:

提供代理实例 proxy 和一个由其代理类 Foo 实现的接口,以下表达式将返回 true:
     proxy instanceof Foo
并且以下的强制转换操作将会成功(而不抛出 ClassCastException):
     (Foo) proxy
每个代理实例都有一个关联的调用处理程序,它会被传递到其构造方法中。静态 Proxy.getInvocationHandler 方法将返回与作为其参数传递的代理实例相关的调用处理程序。
代理实例上的接口方法调用将按照该方法的文档描述进行编码,并被指派到调用处理程序的 Invoke 方法。
在代理实例上的 java.lang.Object 中声明的 hashCode、equals 或 toString 方法的调用将按照与编码和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的 invoke 方法,如上所述。传递到 invoke 的 Method 对象的声明类是 java.lang.Object。代理类不重写从 java.lang.Object 继承的代理实例的其他公共方法,所以这些方法的调用行为与其对 java.lang.Object 实例的操作一样。
在多代理接口中重复的方法
当代理类的两个或多个接口包含一个具有相同名称和参数签名的方法时,代理类的接口顺序变得非常重要。在代理实例上调用重复方法 时,传递到调用处理程序的 Method 对象没有必要成为其声明类可以从接口(通过该接口调用代理方法)的引用类型指派的对象。此限制存在的原因是,生成的代理类中的相应方法实现无法确定它通过哪一个接口调用。因此,在代理实例上调用重复方法时,第一个接口中的方法的 Method 对象包含接口的代理类列表中的方法(直接或通过超级接口继承),该对象会传递到调用处理程序的 invoke 方法,无论该方法调用通过哪一种引用类型发生。

如果代理接口包含某一方法,它的名称和参数签名与 java.lang.Object 的 hashCode、equals 或 toString 方法相同,那么在代理实例上调用这样的方法时,传递到调用处理程序的 Method 对象将使 java.lang.Object 成为其声明类。换句话说,java.lang.Object 公共的非最终方法理论上在所有代理接口之前,以便确定哪一个 Method 对象传递到调用处理程序。

还要注意,当重复方法被指派到调用处理程序时,invoke 方法只可以抛出经过检查的异常类型,该异常类型可以使用所有 代理接口(可以通过它调用)中方法的 throws 子句指派一种异常类型。如果 invoke 方法抛出一个经过检查的异常,该异常没有指派给任何由一个代理接口(可以通过它调用)中的方法声明的异常类型,那么该代理实例上的调用将抛出一个未经检查的 UndeclaredThrowableException。此限制表示并非所有的由传递到 invoke 方法的 Method 对象上调用 getExceptionTypes 返回的异常类型都可以由 invoke 方法成功抛出。

分享到:
评论

相关推荐

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

    JDK动态代理的局限性在于,它只能为实现了至少一个接口的类创建代理,因为代理对象必须继承自这些接口。这种方式适用于那些基于接口进行编程的设计,比如Spring AOP中的Advisor和Advice。 相反,CGLIB(Code ...

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

    JDK 动态代理为什么必须使用接口?这主要是因为 JDK 动态代理是基于接口的代理,它需要一个接口来生成代理类。如果我们想使用 JDK 动态代理,必须提供一个接口,并且将其实现类交给 JDK 动态代理来生成代理类。这样...

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

    JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始类相同的接口,并且在调用接口方法时,可以插入自定义的逻辑。这样,我们就可以在不...

    动态代理和cglib例子

    1. 动态代理:适用于目标对象实现了接口的情况,因为动态代理只能针对接口生成代理。 2. CGLIB:当目标对象没有实现接口或为了性能考虑(接口调用比子类方法调用稍慢)时,可以选择CGLIB。 总结,动态代理和CGLIB都...

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

    JDK动态代理的优点是它完全符合Java语言规范,不需要依赖额外的库,但缺点是只能对实现了接口的类进行代理,无法处理未实现接口的类。 **CGLib动态代理**: CGLib(Code Generation Library)是一个高性能的代码...

    CGLIB 和 JDK生成动态代理类的区别

    JDK动态代理只能为实现了至少一个接口的类生成代理。它的基本原理是利用反射机制生成一个实现了目标接口的子类,然后通过这个子类来调用原对象的方法。因此,如果目标类没有实现任何接口,JDK动态代理就无法工作。 ...

    JDKProxy:用来理解jdk基于接口的动态代理和cglib基于类代理区别的demo

    然而,它的局限性在于只能代理实现了接口的对象,如果目标对象是一个没有接口的类,那么JDK的动态代理就无法使用。 接下来,我们转向CGLIB(Code Generation Library)。CGLIB是一个强大的高性能的代码生成库,它...

    代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)与SpringAOP的3种配置方式案例工程代码

    1. 动态代理只能应用于实现了接口的类,对于没有接口的类无法使用。 2. 由于是运行时生成,可能影响性能。 ### Spring AOP Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了声明式事务管理、日志...

    Java 动态代理和Cglib代理(二)

    然而,Java动态代理有一个局限性,即它只能代理实现了接口的对象,无法代理没有接口的类。为了解决这个问题,Cglib应运而生。 Cglib(Code Generation Library)是一个强大的代码生成库,它可以在运行时动态地生成...

    Java 代理 代理模式 静态代理与动态代理 常见的动态代理实现 .md

    - 缺点:只能用于接口的代理。 - **CGLIB**: - 优点:可以代理任何类,不受限于接口。 - 缺点:生成的代理类会继承原始类,可能导致类层次结构复杂。 #### 5. 动态代理的实际应用——Spring AOP Spring框架...

    基于JAVA的动态代理实现的AOP的研究.pdf

    - 只能代理实现了接口的类,对于没有接口的类无法创建代理。 - 切面逻辑的实现受限于InvocationHandler接口,可能不够直观或强大。 - 对于静态方法或构造函数,动态代理无法提供拦截。 未来,AOP的发展前景广阔,...

    [#0x0042] Spring AOP学习(二):动态代理

    JDK动态代理虽然简单且无需额外依赖,但它的局限性在于只能代理实现了接口的对象。如果目标对象没有实现接口,Spring会自动切换到CGLIB代理,这是一种基于字节码生成技术的代理方式,可以代理没有接口的类。 总的来...

    代理模式(含动态代理讲解)【Spring AOP实质】

    通常我们使用基于接口的动态代理,因为Java只能为实现了接口的类创建代理。 在Spring AOP(面向切面编程)中,代理模式扮演着核心角色。Spring AOP通过代理来实现切面(Aspect),这些切面可以包含横切关注点,如...

    Java动态代理资源包

    - Java标准动态代理(`java.lang.reflect.Proxy`)基于接口,只能代理实现了特定接口的类,而CGLIB则不需要接口。 - CGLIB的性能通常优于Java标准动态代理,因为它的底层是通过字节码生成而非反射,但在未实现接口的...

    动态代理

    - **接口约束**:Java的动态代理只能应用于实现了至少一个接口的类。因为代理对象必须与原对象具有相同的接口,才能保证类型兼容。 2. **CGLib动态代理** - **CGLib(Code Generation Library)**:当原对象没有...

    jdk 动态代理

    - 动态代理只能代理实现了接口的类,不能代理没有接口或实现了final方法的类,因为这些类无法通过字节码操作来插入额外的代码。 - 代理对象与目标对象之间的关系需要在运行时维护,这可能导致代码的可读性和可维护性...

    示例代码:java动态代理和cglib代理的简单例子

    相比于Java动态代理,CGLIB在处理未实现接口的类时更强大,因为它可以创建目标类的子类,而Java动态代理只能代理实现了接口的类。 1. CGLIB的核心类: - `Enhancer`:CGLIB的主要工具类,用于创建子类。 - `...

    JAVA的反射机制与动态代理.pdf

    - **JDK动态代理**:基于接口的代理,需要实现`InvocationHandler`接口。 - **CGLIB**:基于子类的代理,适用于没有实现接口的类。 #### 四、CGLIB动态代理 CGLIB(Code Generation Library)是一个高性能的代码...

    Java动态代理[动态类Proxy的使用]

    本文将深入探讨Java中的动态代理,特别是基于`java.lang.reflect.Proxy`类的使用。 首先,`java.lang.reflect.Proxy`是Java标准库中用于生成动态代理类的关键类。它允许我们创建一个新的接口实现类,而无需手动编写...

Global site tag (gtag.js) - Google Analytics