首先说一下动态代理和静态代理的差别:

静态代理:是预先写好或由特定工具自己主动生成的代码。再对其编译。在程序执行前。代理类的.class文件就已经存在了。

动态代理:代理是在程序执行时,运用反射机制动态创建而成的,程序执行之前,代理是不存在的。

Java的静态代理最简单的场景,一个接口,一个实现类,一个代理类就能够搞定。这个代理类持有接口实现类的引用,这样便能够实现托付对象的增强了。

Java的动态代理主要有两种。JDK动态代理和cglib动态代理

当中JDK动态代理,主要利用了接口InvocationHandler,还有Proxy类。

InvocationHandler接口: 

public interface InvocationHandler { 

 public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 

}

參数说明: 

 Object proxy:指代理对象。 

 Method method:要调用的方法 

 Object[] args:方法调用时所须要的參数 

Proxy类: 

Proxy类是专门完毕代理的操作类,能够通过此类为一个或多个接口的实现类动态地生成代理类,此类提供了例如以下的操作方法: 

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

參数说明: 

 ClassLoader loader:类载入器 

 Class<?

>[] interfaces:得到所有的接口 

 InvocationHandler h:得到InvocationHandler接口的子类实例

动态代理类的字节码在程序执行时由Java反射机制动态生成。无需程序猿手工编写它的源码。动态代理类不仅简化了编程工作,并且提高了软件系统的可扩展性。由于Java 反射机制能够生成随意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 以下看一下我写的一个小样例~

package go.derek;

interface Istudy
{
public void study(String words);
}

上面的接口定义了一个方法。

以下是这个接口的实现类

package go.derek;

class StudyImpl implements Istudy
{
public void study(String words){
System.out.println(words);
}
}

以下看一下代理类的代码

package go.derek;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class StudyProxy implements InvocationHandler
{
private Object target;
public Object bind(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
System.out.println("start");
Object obj=method.invoke(target,args);
System.out.println("rest");
return obj;
} }

以下是測试类的代码

package go.derek;

class ProxyTest
{
public static void main(String[] args)
{
StudyProxy sp=new StudyProxy();
Istudy derek=(Istudy)sp.bind(new StudyImpl());
derek.study("I'm derek");
}
}

以下是输出结果:

start

I'm derek

rest

我们能够看出,代理类确实给托付类实现了增强,不能忽视的是代理类要持有托付类对象的引用。

JDK的动态代理机制仅仅能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖当中方法实现增强,但由于採用的是继承。所以不能对final修饰的类进行代理。

JDK动态代理具体解释的更多相关文章

  1. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  2. 【原创】JDK动态代理,此次之后,永生难忘。

    动态代理,这个词在Java的世界里面经常被提起,尤其是对于部分(这里强调“部分”二字,因为有做了一两年就成大神的,实力强的令人发指,这类人无疑是非常懂动态代理这点小伎俩的)做了一两年新人来说,总是摸不 ...

  3. MyBatis Mapper 接口如何通过JDK动态代理来包装SqlSession 源码分析

    我们以往使用ibatis或者mybatis 都是以这种方式调用XML当中定义的CRUD标签来执行SQL 比如这样 <?xml version="1.0" encoding=& ...

  4. JDK 动态代理分析

    Java的代理有两种:静态代理和动态代理,动态代理又分为 基于jdk的动态代理 和 基于cglib的动态代理 ,两者都是通过动态生成代理类的方法实现的,但是基于jdk的动态代理需要委托类实现接口,基于 ...

  5. JDK动态代理[4]----ProxyGenerator生成代理类的字节码文件解析

    通过前面几篇的分析,我们知道代理类是通过Proxy类的ProxyClassFactory工厂生成的,这个工厂类会去调用ProxyGenerator类的generateProxyClass()方法来生成 ...

  6. Java JDK动态代理解析

    动态代理虽不常自己实现,但在Spring或MyBatis中都有重要应用.动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问.Spring常JDK和CGLIB动态代理 ...

  7. JDK动态代理给Spring事务埋下的坑!

    一.场景分析 最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1.场景A ...

  8. 转:jdk动态代理实现

    原文链接: jdk动态代理 注:文章中用常用的流程实现 动态代理,流程逻辑比较清晰.文章后面对 “为什么要使用接口” 原理分析还未细看. jdk的动态代理为什么用接口,内部是什么原理呢?看了几篇文章貌 ...

  9. (转)面试必备技能:JDK动态代理给Spring事务埋下的坑!

    一.场景分析 最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1.场景A ...

随机推荐

  1. 最小公倍数 【杭电-HDOJ-1108】 附题+具体解释

    /* 最小公倍数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  2. spring-boot 集成 swagger 问题的解决

    spring-boot 集成 swagger 网上有许多关于 spring boot 集成 swagger 的教程.按照教程去做,发现无法打开接口界面. 项目由 spring mvc 迁移过来,是一个 ...

  3. Android Exception 11(baidumapsdk(15405): Authentication Error errorcode: 102 uid)

    08-12 16:06:12.622: E/baidumapsdk(15405): Authentication Error errorcode: 102 uid: null appid -1 msg ...

  4. js实现图片的等比例缩放

      js实现图片的等比例缩放 CreateTime--2018年3月6日14:04:18 Author:Marydon 1.代码展示 /** * 图片按宽高比例进行自动缩放 * @param ImgO ...

  5. winfrom cahce 问题

    .Clear()不能随便用 .Clear()的比较没有什么意思,因为只是把DataTable清空而已,在堆中任然分配内存,一般要比较也是比较Close()方法,不过DataTable没有这个方法 至于 ...

  6. openfireserver和jdk环境删除命令

    一.卸载jdk1.8 终端依次运行以下的命令 sudo rm -fr /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin sudo rm -rf / ...

  7. CENTOS 下安装APK反编译工具 APKTOOL

    转于:http://www.qiansw.com/centos-apk-apktool.html 我使用的是CentOS6.4 64位的系统.首先需要下载两个包.这里下载:https://code.g ...

  8. 利用dd命令制作u盘iso镜像

    现在安装系统都是用u盘安装,那么制作u盘的iso镜像就是必须的了.现在此类工具倒是不少,但是,好用的不多,有的还收费.唉,还是用dd吧,老配方,老味道. 首先:要df -h一下,看看u盘的盘符,类似  ...

  9. 关于Unity实现游戏录制功能的思考

    录制无非两种做法,录制操作和录制行为. 录制操作要考虑到随机行为,但其实也可以两者混合.如果随机行为过多,并且随机行为无法用种子复现,可以完全用录制的方式 最后再统一压缩 这里yy的就是录制行为的做法 ...

  10. linux下启动、添加或删除服务命令

    在Linux系统下,一个Services的启动.停止以及重启通常是通过/etc/init.d目录下的脚本来控制的.然而,在启动或改变运行级别时,是在/etc/rcX.d中来搜索脚本.其中X是运行级别的 ...