===========================================

    原文链接: 动态代理的两种实现方式(JDK/Cglib) 转载请注明出处!

===========================================

什么是代理模式?(设计模式—代理模式)
  代理模式:在调用处不直接调用目标类进行操作,而是调用代理类,然后通过代理类来调用目标类进行操作。在代理类调用目标类的前后可以添加一些预处理和后处理操作来完成一些不属于目标类的功能。
为什么要使用代理模式?
  通过代理模式可以实现对目标类调用的控制、在目标类调用前/后进行一些不属于目标类的操作,如:数据验证、预处理、后处理、异常处理等
什么是静态代理什么是动态代理?
  静态代理:代理类只能实现对”特定接口的实现类“进行代理
  动态代理:代理类可以实现对多种类的代理
jdk代理和cglib代理区别在哪里?
  jdk动态代理:代理所有“实现的有接口”的目标类
     cglib动态代理:代理任意一个目标类,但对final类和方法无法代理
     不同点:jdk动态代理的目标类必须实现的有接口,因为在调用Proxy.newProxyInstance()的时候需要传入目标类的接口类。而cglib不做此限制。

   下面看代码分析:

定义一个Person接口

package com.zpj.designMode.proxy;

//定义一个Person接口
public interface Person {
public void doWork();
}

添加一个实现类:MrLi

package com.zpj.designMode.proxy;

//添加一个实现类
public class MrLi implements Person { @Override
public void doWork() {
System.out.println("-----doWork");
} }

静态代理:

 添加一个静态代理类Proxy

package com.zpj.designMode.proxy;

//静态代理,代理必须和目标类实现共同的接口
public class Proxy implements Person {
private Person person;// 被代理人 //这里的目标类型决定了该代理类只能代理实现了Person接口的实例,而不能接收其他类型参数,这也就是静态代理的局限性
public Proxy(Person person) {
this.person = person;
} @Override
public void doWork() {
System.out.println("doSomething-----start");
person.doWork();
System.out.println("doSomething-----end");
} }

静态代理测试程序:

package com.zpj.designMode.proxy;

public class Run {
public static void main(String[] args) {
MrLi li = new MrLi();
Proxy proxy = new Proxy(li);
//调用处直接调用代理进行目标方法的操作。
proxy.doWork();
}
}

JDK动态代理:

添加一个代理JDKProxy,该代理实现InvocationHandler接口且覆写invoke方法。

package com.zpj.designMode.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /***
@author Perkins Zhu
@date 2017年3月13日 上午8:41:10
*/
public class JDKProxy implements InvocationHandler { private Object person;// 被代理人 //这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理。但是要注意下面的newProxyInstance()中的参数
public Object getInstance(Object person) {
this.person = person;
//与cglib的区别在于这里构建代理对象的时候需要传入被代理对象的接口对象,第二个参数。而cglib不需要被代理对象实现任何接口即可
return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("doSomething---------start");
method.invoke(person, args);
System.out.println("doSomething---------end");
return null;
} }

JDK动态代理测试程序

package com.zpj.designMode.proxy.jdk;

import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person; /***
* @author Perkins Zhu
* @date 2017年3月13日 上午8:51:31
*/
public class Run { public static void main(String[] args) {
Person person = (Person) new JDKProxy().getInstance(new MrLi());
//注意这里的person不是目标类person,而是代理类person:debug的时候显示null,有'$'标识符
person.doWork();
}
}

Cglib动态代理:

添加一个CglibProxy代理,同时实现MethodInterceptor接口。

package com.zpj.designMode.proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; /***
* @author Perkins Zhu
* @date 2017年3月13日 上午9:02:54
*/
public class CglibProxy implements MethodInterceptor {
private Object targetObject; // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
public Object getInstance(Object target) {
this.targetObject = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
//注意该处代理的创建过程
Object proxyObj = enhancer.create();
return proxyObj;// 返回代理对象
} @Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
System.out.println("doSomething---------start");
obj = method.invoke(targetObject, args);
System.out.println("doSomething---------end");
return obj;
} }

Cglib动态代理测试程序

package com.zpj.designMode.proxy.cglib;

import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person; /***
@author Perkins Zhu
@date 2017年3月13日 上午9:07:38
*/
public class Run { public static void main(String[] args) {
Person person = (Person)new CglibProxy().getInstance(new MrLi());
person.doWork();
}
}

仔细对比Proxy、CglibProxy和JDKProxy区分静态代理、JDK动态代理和Cglib动态代理的异同点!

-------end

动态代理的两种实现方式(JDK/Cglib)的更多相关文章

  1. Java动态代理的两种实现方式:

    方式一:传统的代理 package cn.hc.domain; import java.lang.reflect.InvocationHandler; import java.lang.reflect ...

  2. java动态代理的两种方法

    动态代理,有两种情况,第一种是有接口的情况下,你可以选择为jdk自带的动态代理的方式来编写程序,但你想要为一个实在的类编写动态代理的方式的话,这时候就必须选择一些开源的lib包,如cglib包,同时还 ...

  3. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  4. java动态代理的2种实现方式

    java的动态代理在接java的api上有说明,这里就不写了.我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理.代理是通过代理实例关联的调用处理程序对象调用方法. 下面通过一个例子看一下 ...

  5. spring aop提供了两种实现方式jdk和cglib

    Spring AOP使用了两种代理机制:一种是基于JDK的动态代理:另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理. Sprin ...

  6. Java动态代理的两种实现方法

    注:文章转载自:https://blog.csdn.net/m0_38039437/article/details/77970633 一.代理的概念 动态代理技术是整个java技术中最重要的一个技术, ...

  7. Java实现动态代理的两种方式

    http://m.blog.csdn.net/article/details?id=49738887

  8. JDK动态代理(Proxy)的两种实现方式

    JDK自带的Proxy动态代理两种实现方式 前提条件:JDK Proxy必须实现对象接口 so,创建一个接口文件,一个实现接口对象,一个动态代理文件 接口文件:TargetInterface.java ...

  9. Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式

    封面:洛小汐 作者:潘潘 一直以来 他们都说为了生活 便追求所谓成功 顶级薪水.名牌包包 还有学区房 · 不过 总有人丢了生活 仍一无所获 · 我比较随遇而安 有些事懒得明白 平日里问心无愧 感兴趣的 ...

随机推荐

  1. 【原创】NuGet 出现“无法初始化 PowerShell 主机,如果将你的 PowerShell 执行策略设置设置为 AllSigned ,请先打开程序包管理控制台以初始化该主机” 错误的解决方法

    现象: 网上的设置 AllSigned 等方法都无效..后来考虑可能跟命令行版本兼容性有关系,然后在注册表命令行配置里发现一 ForceV2 设置项,抱着试一试的心态改了下,果然解决了! 解决方法:修 ...

  2. 理解zookeeper选举机制

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  3. BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)

    首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...

  4. Angular2 Service实践——实现简单音乐播放服务

    引言: 如果说组件系统(Component)是ng2应用的躯体,那把服务(Service)认为是流通于组件之间并为其带来生机的血液再合适不过了.组件间通信的其中一种优等选择就是使用服务,在ng1里就有 ...

  5. p1217晚餐(简单的dijkstra)

    题目: 输入: 1000 5 61 2 3002 4 2003 4 6003 4 8005 3 1002 5 650 输出: 4 这道题呢,其实就是用邻接矩阵将每条边耗费的体力存起来,然后用dijks ...

  6. Kettle 4.4.2源码分析

    一.获取并编译源码 1.1.获取源码 SVN:svn://source.pentaho.org/svnkettleroot/archive/Kettle/branches GitHub:https:/ ...

  7. 每天一个Linux命令(06)--rmdir命令

    终于忙完了公司的事,可以安静的充充电了. 今天学习一下Linux中命令:rmdir 命令,rmdir是常用的命令,该命令的功能是删除空目录,一个目录被删除之前必须是空的.(注意,rm -r dir 命 ...

  8. Pdf File Writer 中文应用(PDF文件编写器C#类库)

    该文由小居工作室(QQ:2482052910)    翻译并提供解答支持,原文地址:Pdf File Writer 中文应用(PDF文件编写器C#类库):http://www.cnblogs.com/ ...

  9. ThreadLocal笔记

    1.ThreadLocal的作用是什么?        ThreadLocal是一个泛型类,将保存在其中的值与当前的线程关联起来,这样每个线程看到的值对于其他线程来说都是不可见的,这个技术被称为线程封 ...

  10. 算法模板——Trie树

    实现功能——实现对于不同字符串以及之前出现过的字符串的识别,对于单个长度为L的字符串,复杂度为O(L); 代码不难懂,直接上(在识别字符串方面,个人觉得其好处远远大于hash识别——1.理论上都是O( ...