动态代理的两种实现方式(JDK/Cglib)
===========================================
原文链接: 动态代理的两种实现方式(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)的更多相关文章
- Java动态代理的两种实现方式:
方式一:传统的代理 package cn.hc.domain; import java.lang.reflect.InvocationHandler; import java.lang.reflect ...
- java动态代理的两种方法
动态代理,有两种情况,第一种是有接口的情况下,你可以选择为jdk自带的动态代理的方式来编写程序,但你想要为一个实在的类编写动态代理的方式的话,这时候就必须选择一些开源的lib包,如cglib包,同时还 ...
- 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)
Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC 目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...
- java动态代理的2种实现方式
java的动态代理在接java的api上有说明,这里就不写了.我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理.代理是通过代理实例关联的调用处理程序对象调用方法. 下面通过一个例子看一下 ...
- spring aop提供了两种实现方式jdk和cglib
Spring AOP使用了两种代理机制:一种是基于JDK的动态代理:另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理. Sprin ...
- Java动态代理的两种实现方法
注:文章转载自:https://blog.csdn.net/m0_38039437/article/details/77970633 一.代理的概念 动态代理技术是整个java技术中最重要的一个技术, ...
- Java实现动态代理的两种方式
http://m.blog.csdn.net/article/details?id=49738887
- JDK动态代理(Proxy)的两种实现方式
JDK自带的Proxy动态代理两种实现方式 前提条件:JDK Proxy必须实现对象接口 so,创建一个接口文件,一个实现接口对象,一个动态代理文件 接口文件:TargetInterface.java ...
- Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式
封面:洛小汐 作者:潘潘 一直以来 他们都说为了生活 便追求所谓成功 顶级薪水.名牌包包 还有学区房 · 不过 总有人丢了生活 仍一无所获 · 我比较随遇而安 有些事懒得明白 平日里问心无愧 感兴趣的 ...
随机推荐
- 反汇编看c++引用
继续反汇编系列,本次使用vc2008在x86体系下分析c++中的引用. 定义一个引用类型和将一个变量转换成引用类型一样吗? 引用比指针安全,真的是这样吗,对引用不理解的话比指针还危险. 为什么要用常量 ...
- Ffmpeg 视频教程
最近一段时间找时间录制了一些Ffmpeg视频教程,还有录制完毕,会持续更新,内容会包含Ffmeg保存文件,网络流转发, 编码,解码,播放器制作,以及服务端搭建等等,适合初学者,有需要的朋友的可以关注: ...
- 跟着内核学框架-从misc子系统到3+2+1设备识别驱动框架
misc子系统在Linux中是一个非常简单的子系统,但是其清晰的框架结构非常适合用来研究设备识别模型.本文从misc子系统的使用出发,通过了解其机制来总结一套的设备识别的驱动框架,即使用使用同一个驱动 ...
- 获取CPU和内存呢信息
#include <stdio.h> #include <stdlib.h> #include <winsock.h> #pragma comment(lib, & ...
- 《汇编语言程序设计》——仿windows计算器
<汇编语言程序设计> ——计算器程序设计 目录 一. 题目与目标 1. 题目 2. 学习目的 二. 分析与设计 1. 系统分析 2. ...
- 在SQL Server里如何处理死锁
在今天的文章里,我想谈下SQL Server里如何处理死锁.当2个查询彼此等待时会发生死锁,没有一个查询可以继续它们的操作.首先我想给你大致讲下SQL Server如何处理死锁.最后我会展示下SQL ...
- canvas实例:旋转缩放的方块
首先在页面中创建一个canvas标签: <body> <canvas id="c1" width="500" height="500 ...
- Angular.js之服务与自定义服务学习笔记
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 1. Two Sum★
题目内容:Given an array of integers, return indices of the two numbers such that they add up to a specif ...
- Redis简单配置和使用
学到Redis中需要整理和配置的东西比较多,资源也是比较分散!这次的主要还是将知识整合一下,开发过程中所需要的资源整合一下,也方便今后涉及到这块地方的知识时,将时间大量浪费在了找这些资源上了! 一.R ...