什么是动态代理呢?
就是在java的运行过程中,动态的生成的代理类。(为了更熟悉的了解动态代理,你必须先熟悉代理模式,可点击设计模式之代理模式 阅读)
我们知道java属于解释型语言,是在运行过程中,寻找字节码文件从而实现类加载的。
但是字节码文件并不需要一定是硬盘中的class文件,也可以是来自网络、数据库或者是直接生成的数据流。因此这就给虚拟机动态的生成代理类提供了可能。
Java 1.3 正式引入,动态代理(Dynamic proxies)特性。
前一篇文章我们已经知道Proxy是代理模式的核心,而动态代理就是在运行期间由虚拟机根据需要,动态的生成出这样一个代理类。
我们可以直接看java的实现方法:

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; public class DynamicProxyInvoker
{
public static void main(String[] args)
{
InvocationHandler proxyHandler = new SuperStarInvocationHandler("messi");
ISuperStar superStarDynamicProxy = (ISuperStar) Proxy.newProxyInstance(ISuperStar.class.getClassLoader(), new Class<?>[]
{ ISuperStar.class }, proxyHandler);
superStarDynamicProxy.signContract();
superStarDynamicProxy.negotiate();
}
}
 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class SuperStarInvocationHandler implements InvocationHandler
{
private String proxyName;
ISuperStar superStar; public SuperStarInvocationHandler(String startName)
{
this.proxyName = startName + "'s proxy";
superStar = new SuperStar(startName);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println(proxyName + " signContract");
Object object = method.invoke(superStar, args);
return object;
} }
 public interface ISuperStar
{
/**
* 签约
*/
public void signContract(); /**
* 谈判
*/
public void negotiate();
}
 public class SuperStar implements ISuperStar
{
private String starName;
public SuperStar(String starName)
{
this.starName=starName;
} @Override
public void signContract()
{
System.out.println(starName+" signContract");
// to do sth
return;
} @Override
public void negotiate()
{
System.out.println(starName+" negotiate");
// to do sth
return;
}
}

superStarDynamicProxy是由系统自动生成的,一个实现了接口ISuperStar的类。这个类并不存在于具体的实现。同时由于系统也不知道我们具体需要在代理类中做哪些的操作。
因此需要我们自己提前安排好一个处理类SuperStarInvocationHandler。这个处理类中实现了代理类中是如何调用实现类中的方法的逻辑。
他们的调用关系图是这样的:


       我们可以看到动态代理的结构图中,代理方并不会直接调用到被代理方,而是通过业务处理类来调用的。因此业务处理类需要保持一个被代理方的实例对象。(非强制)通过虚拟机主动生成动态代理类,我们可以发现,调用方和被调用方在代码实现阶段其实是断层的。并不存在依次的直接调用关系。因此耦合的概念会更浅。同时由于不再需要为像静态代理那样为每个类都实现一个代理类,因此以切面的形式加入代理层成为可能。这个我会在后续的文章中介绍。

ps :有兴趣的同学可以在main方法中手动的将动态代理生成的代理方superStarDynamicProxy的字节码导入到一个.class文件中,然后反编译该文件。你就会发现,这个类其实就是被代理方所实现接口的一个适配类。其中的所有方法的实现都是调用业务处理类SuperStarInvocationHandler,再由业务处理类通过反射动态的调用到SuperStar类的。

动态代理的不足

1、早期由于jdk反射的性能有限,因此jdk的动态代理方式在性能上并不是很优越,但是随着jdk对于反射性能的优化,此处的性能损耗已经越来越小。
2、从构建动态代理类的源码(有兴趣的同学也可以按照前文的形式反编译),或者是手动添加一个Instance Proxy的形式。
我们可以发现,代理类其实是继承自Proxy的同时实现了接口。因此动态代理只能用来解决接口动态代理的场景,因为java是不允许集成自多个类的。此问题可以使用CGLIB来解决,有兴趣的同学可以自己看下,这个我会在后边的文章中介绍。

设计模式之Jdk动态代理的更多相关文章

  1. 设计模式之jdk动态代理模式、责任链模式-java实现

    设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...

  2. Java设计模式之JDK动态代理原理

    动态代理核心源码实现public Object getProxy() { //jdk 动态代理的使用方式 return Proxy.newProxyInstance( this.getClass(). ...

  3. Java JDK 动态代理使用及实现原理分析

    转载:http://blog.csdn.net/jiankunking   一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理 ...

  4. JDK动态代理与Cglib库

    JDK动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在 ...

  5. Java设计模式系列之动态代理模式(转载)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...

  6. JDK动态代理实现简单AOP--转

    JDK 动态代理是 java 反射的一个重要特性.它在某种方面为 java 提供了动态性的特性,给应用带来了无限的空间.大名鼎鼎的 Hessian . Spring AOP 基于动态代理实现.本文将简 ...

  7. JDK动态代理实现机制

    =========================================== 原文链接: JDK动态代理实现机制   转载请注明出处! =========================== ...

  8. 017 Java中的静态代理、JDK动态代理、cglib动态代理

    一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...

  9. SSM-Spring-09:Spring中jdk动态代理

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- JDK动态代理: 为何叫JDK动态代理呢? 所谓JDK,jdk是java开发工具包,它里面包含了一个动态代理的 ...

随机推荐

  1. android ListView 分页加载数据

    1.mainActivity <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ...

  2. Linux之Ubuntu无线网络配置

    无线网络使用问题: 0.插上有线网络电线与电脑NIC上. 1.set->系统设置->软件和更新->Ubuntu软件->下载自:   选择一个网络服务器地址(软件源)[http: ...

  3. Centos7下编译CDH版本hadoop源码支持Snappy压缩

    1 下载snappy包并编译 wget https://github.com/google/snappy/releases/download/1.1.3/snappy-1.1.3.tar.gz tar ...

  4. mysql 案例 ~ 瘦身mysql系列(1)

    一 简介:这一系列我们要进行如何瘦身mysql 二 目的:通过提高CPU利用率和节约成本,降低数据库容量及I/O负载,从而使数据吞吐率得到显著提高 三 方法: 利用innodb的COMPRESSED ...

  5. CMake 实践教程

    本篇博客是根据 <<CMake Practice>> 一文编写, 目的有三: 其一: 提取出其中的精要部分; 其二: 对其中不易理解的地方进行简要说明; 其三: 方便后续查找复 ...

  6. 转载: 使用vue全家桶制作博客网站 HTML5 移动网站制作的好教程

    使用vue全家桶制作博客网站   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用vue全家桶制作的博客网站 概述 该项目是基于vue全家桶(vue. ...

  7. 使用JDBC连接数据库报“找不到驱动程序”错误解决

    1.jre安装不成功: 2.jre中没有数据库驱动(D:\jre\lib\ext 中查看)

  8. LeetCode(34):搜索范围

    Medium! 题目描述: 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果 ...

  9. wpf 来回拉动滚动条抛异常

    其中的控件,来回快速的来动滚动条,抛如下异常,但是完全代码捕捉不到. 这个树用到了VirtualizingStackPanel.IsVirtualizing="True".去掉该句 ...

  10. Laravel API 限速异常 HTTPException Too Many Attemps

    最近线上 Laravel 错误日志发现了一个异常 HTTPException Too Many Attemps 而我一个同事在本地开发的过程中也频繁遇到这个异常.测试环境:Laravel 5.5. 网 ...