彻底搞懂代理模式实现原理
什么是代理模式
代理模式主要对我们方法执行之前与之后实现增强
代理模式应用场景
1.日志的采集
2.权限控制
3.实现aop
4.Mybatis mapper
5.Spring的事务
6.全局捕获异常
7.Rpc远程调用接口
8.代理数据源
9.自定义注解+反射+aop技术
核心思想:解决代码的冗余性的问题
代理模式实现的原理
抽象主题角色:可以是接口,也可以是抽象类;
委托类角色:真实主题角色,业务逻辑的具体执行者;
代理类角色:内部含有对真实对象ServiceImpl的引用,负责对真实主题角色的调用,并在真实主题角色处理前后做预处理和后处理。
代理模式创建方式
静态代理
静态代理需要自己人工编写代理类代码
基于接口实现方式
public class OrderServiceProxy implements OrderService{
private OrderService orderService;
public OrderServiceProxy(OrderService orderService) {
this.orderService = orderService;
}
public String addOrder(String userName, String userPwd) {
System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd);
String result = orderService.addOrder(userName, userPwd);
System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd);
return result;
}
}
public interface OrderService {
/**
* 需要被代理的方法
* @return
*/
String addOrder(String userName,String userPwd);
}
public class Test001 {
public static void main(String[] args) {
OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());
orderService.addOrder("mayikt","123456");
}
}
基于继承的实现方式
public class OrderServiceProxy extends OrderServiceImpl {
private OrderService orderService;
public OrderServiceProxy(OrderService orderService) {
this.orderService = orderService;
}
public String addOrder(String userName, String userPwd) {
System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd);
String result = super.addOrder(userName, userPwd);
System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd);
return result;
}
}
动态代理与静态代理的区别
动态代理不需要写代理类对象,通过程序自动生成,而静态代理需要我们自己写代理类对象。
Jdk生成字节码技术
ASM
动态代理
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成 。
Jdk动态代理
JDK动态代理的一般步骤如下:
1.创建被代理的接口和类;
2.实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
3.调用Proxy的静态方法,创建代理类并生成相应的代理对象;
实现原理:利用拦截器机制必须实现InvocationHandler接口中的invoke方法实现对
我们的目标方法增强。
public class JdkInvocationHandler implements InvocationHandler {
/**
* 目标对象
*/
private Object target;
public JdkInvocationHandler(Object target) {
this.target = target;
}
/**
* @param proxy 使用jdk程序生成的代理类
* @param method 目标方法
* @param args 方法需要传递的参数
* @return
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
Object result = method.invoke(target, args);
System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
return result;
}
/**
* 生成代理类
*
* @param <T>
* @return
*/
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
public class JdkInvocationHandler implements InvocationHandler {
/**
* 目标对象
*/
private Object target;
public JdkInvocationHandler(Object target) {
this.target = target;
}
/**
* @param proxy 使用jdk程序生成的代理类
* @param method 目标方法
* @param args 方法需要传递的参数
* @return
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
Object result = method.invoke(target, args);
System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
return result;
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl());
OrderServiceImpl orderService = jdkInvocationHandler.getProxy();
orderService.addOrder("mayikt", "meite");
加上该代码:
1.获取代理的生成的class文件
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);
2.使用反编译工具该Proxy0.class
注意:继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。
纯手写Jdk动态代理
思路分析:
1.定义InvocationHandler类 回调方法
2.使用java反射技术获取接口下所有的方法,拼接
P
r
o
x
y
0.
j
a
v
a
代
码
3.
在
将
Proxy0.java代码 3.在将
Proxy0.java代码3.在将Proxy0.java编译成class文件,读取到内存中
public class $Proxy0 implements com.mayikt.service.OrderService {
private MayiktJdkInvocationHandler h;
private static Method m3;
public $Proxy0(MayiktJdkInvocationHandler mayiktJdkInvocationHandler) {
this.h = mayiktJdkInvocationHandler;
}
@Override
public String addOrder(String ver1, String var2) {
try {
return (String) h.invoke(this, m3, new Object[]{ver1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
static {
try {
m3 = Class.forName("com.mayikt.service.OrderService").getMethod("addOrder", Class.forName("java.lang.String"), Class.forName("java.lang.String"));
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler {
/**
* 目标对象
*/
private Object target;
public MyJdkInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
Object result = method.invoke(target, args);
System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
return result;
}
public <T> T getProxy() {
return (T) new $Proxy0(this);
}
}
MyJdkInvocationHandler myJdkInvocationHandler = new MyJdkInvocationHandler(new OrderServiceImpl());
OrderService orderService = myJdkInvocationHandler.getProxy();
orderService.addOrder("mayikt", "meite");
public class MyProxy {
private static String rt = "\r\t";
public static Object newProxyInstance(JavaClassLoader classLoader, Class classInfo, MayiktInvocationHandler mayiktInvocationHandler) {
try {
// 1.拼接java代理代理源代码
Method[] methods = classInfo.getMethods();
String proxyClass = "package com.mayikt.service;" + rt
+ "import java.lang.reflect.Method;" + rt
+ "import com.mayikt.service.proxy.MayiktInvocationHandler;" + rt
+ "import java.lang.reflect.UndeclaredThrowableException;" + rt
+ "public class $Proxy0 implements " + classInfo.getName() + "{" + rt
+ "MayiktInvocationHandler h;" + rt
+ "public $Proxy0(MayiktInvocationHandler h)" + "{" + rt
+ "this.h= h;" + rt + "}"
+ getMethodString(methods, classInfo) + rt + "}";
// 2.将该源代码写入到本地文件中
String filename = "d:/code/$Proxy0.java";
File f = new File(filename);
FileWriter fw = new FileWriter(f);
fw.write(proxyClass);
fw.flush();
fw.close();
// 3.编译为class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(filename);
JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
// 4.将class文件加入到内存中
Class proxy0Class = classLoader.findClass("$Proxy0");
//5.使用java反射机制给函数中赋值
Constructor m = proxy0Class.getConstructor(MayiktInvocationHandler.class);
Object object = m.newInstance(mayiktInvocationHandler);
return object;
} catch (Exception e) {
return null;
}
}
public static String getMethodString(Method[] methods, Class intf) {
String proxyMe = "";
for (Method method : methods) {
Class<?>[] parameterTypes = method.getParameterTypes();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parameterTypes.length; i++) {
sb.append(parameterTypes[i].getName() + " ver" + (i + 1));
if (i < parameterTypes.length - 1) {
sb.append(" ,");
}
}
String parameterStr = sb.toString();
proxyMe = "public " + method.getReturnType().getName() + " " + method.getName() + " ( " + parameterStr + " ) { " +
"try { Method m3 = Class.forName(\"com.mayikt.service.OrderService\").getMethod(\"addOrder\", Class.forName(\"java.lang.String\"), Class.forName(\"java.lang.String\"));" +
"return (String) h.invoke(this, m3, new Object[]{ver1, ver2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } " +
"" +
" } ";
}
return proxyMe;
}
public static void main(String[] args) {
newProxyInstance(null, OrderService.class, null);
}
}
public class JavaClassLoader extends ClassLoader {
private File classPathFile;
public JavaClassLoader(){
// String classPath=JavaClassLoader.class.getResource("").getPath();
String classPath="D:\\code";
this.classPathFile=new File(classPath);
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
String className= JavaClassLoader.class.getPackage().getName()+"."+name;
if(classPathFile!=null){
File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class");
if(classFile.exists()){
FileInputStream in=null;
ByteArrayOutputStream out=null;
try {
in=new FileInputStream(classFile);
out=new ByteArrayOutputStream();
byte[] buff=new byte[1024];
int len;
while ((len=in.read(buff))!=-1){
out.write(buff,0,len);
}
return defineClass(className,out.toByteArray(),0,out.size());
}catch (Exception e){
e.printStackTrace();
}finally {
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
}
public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler {
/**
* 目标对象
*/
private Object target;
public MyJdkInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
Object result = method.invoke(target, args);
System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
return result;
}
public <T> T getProxy() {
return (T) MyProxy.newProxyInstance(new JavaClassLoader(), target.getClass().getInterfaces()[0], this);
}
}
JDK动态代理总结
JDK动态代理是基于我们接口的形式来实现代理的
1.JDK动态代理生成代理类(Proxy(自增))
2.调用addOrder方法时(Proxy0 中的 addOrder方法)
3.Proxy0#addOrder JdkInvocationHandler# invoke
4.直接通过反射机制调用到目标方法(传递目标对象)
JDK动态代理 执行目标方法比CGLIB执行
目标方法简单非常多。
CGLIB动态代理
利用asm字节码技术,生成子类实现对目标方法实现增强
CGLIB动态代理与JDK动态代理实现原理思想都是差不多
CGLIB JDK动态代理
1.程序在运行时自动生成代理类.class
2.类加载器机制将该class读取到程序中;
3.执行目标方法—
实现方式
Maven依赖
cglib
cglib
3.2.12
核心代码
public class CglibMethodInterceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("<<<<<日志收集开始...>>>>>>>");
Object reuslt = proxy.invokeSuper(obj, args);
System.out.println("<<<<<日志收集结束...>>>>>>>");
return reuslt;
}
}
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
Enhancer enhancer = new Enhancer();
// 设置代理类的父类
enhancer.setSuperclass(MemberServiceImpl.class);
// 设置回调对象
enhancer.setCallback(cglibMethodInterceptor);
// 创建代理对象
MemberServiceImpl orderServiceImpl = (MemberServiceImpl) enhancer.create();
orderServiceImpl.getMember();
Cglib动态代理底层源码分析
CGLIB底层生成class -3个;
JDK动态代理生成class --1个;
OrderServiceImpl
E
n
h
a
n
c
e
r
B
y
C
G
L
I
B
EnhancerByCGLIB
EnhancerByCGLIBe5d00400 CGLIB动态代理
生成的 代理类
OrderServiceImpl
F
a
s
t
C
l
a
s
s
B
y
C
G
L
I
B
FastClassByCGLIB
FastClassByCGLIB6d79ead4 ## 目标对象中
目标方法 对应的fastclass 索引 index
OrderServiceImpl
E
n
h
a
n
c
e
r
B
y
C
G
L
I
B
EnhancerByCGLIB
EnhancerByCGLIBe5d00400
F
a
s
t
C
l
a
s
s
B
y
C
G
L
I
B
FastClassByCGLIB
FastClassByCGLIB36b9e032
Cglib代理方法 CGLIB$addOrder$0 对应的fastclass 索引 index
1.cglib 动态代理生成的代理类 继承目标对象
2.jdk动态代理生成的代理类 实现了目标对象所实现的接口
jdk动态代理 基于目标对象的接口实现代理
cglib 动态代理 直接 继承我们 目标对象实现代理
cglib动态代理 底层实现原理
1.cglib动态代理 在生成代理类的class 时,
2.通过代理类的 setCallback 传递我们开发者自己定义好的 CGLIBMethodInterceptor
2.当我们调用到代理类中#addOrder方法时
// 1.获取到 CGLIBMethodInterceptor
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
//2.执行CGLIBMethodInterceptor 的intercept方法
var10000.intercept(this, CGLIB$addOrder$0$Method, new Object[]{var1, var2}, CGLIB$addOrder$0$Proxy);
} else {
super.addOrder(var1, var2);
}
CGLIB不是基于反射机制调用(C编写的)到目标方法而是通过
Fastclass 索引的机制(java实现)
反射机制调用目标方法 -----一行
CGLIB 生成的代理 调用我们的目标方法 Fastclass 建立索引机制
直接调用我们的目标方法(class文件体现)
Fastclass 如何执行到目标方法:
private static class FastClassInfo
{
FastClass f1; ### OrderServiceImpl$$FastClassByCGLIB$$6d79ead4 目标对象中 目标方法 对应fastclass
FastClass f2; ### OrderServiceImpl$$EnhancerByCGLIB$$e5d00400$$FastClassByCGLIB$$36b9e032
int i1; ### addOrder(Ljava/lang/String;Ljava/lang/Integer;)V 目标方法 在
Fastclass 中对应的 index;
int i2; ## CGLIB$addOrder$0 CGLIB代理方法
}
fci.i1 = fci.f1.getIndex(sig1); OrderServiceImpl$$FastClassByCGLIB$$6d79ead4#getIndex方法
fci.i2 = fci.f2.getIndex(sig2);OrderServiceImpl$$EnhancerByCGLIB$$e5d00400$$FastClassByCGLIB$$36b9e032
#getIndex方法
OrderServiceImpl$$EnhancerByCGLIB$$e5d00400###cglib生成的代理类;
OrderServiceImpl$$FastClassByCGLIB$$6d79ead4 ###CglibFastClass
Cglib依赖于ASM字节码技术,直接生成class文件,在采用类加载器读取到程序中,
使用fastclass对被代理类的方法建立索引文件不需要依赖于反射查找到目标方法
CGLIB 早期 发现 如果反射技术调用目标方法效率非常低,
想能够实现直接类似于 开发者 java代码的形式调用目标方法提高效率。
public class OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c extends OrderServiceImpl {
static void CGLIB$STATICHOOK1() throws ClassNotFoundException {
Method amethod[];
Method amethod1[];
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class class1 = Class.forName("com.mayikt.service.impl.OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c");
Class class2;
amethod = ReflectUtils.findMethods(new String[]{
"addOrder", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
}, (class2 = Class.forName("com.mayikt.service.impl.OrderServiceImpl")).getDeclaredMethods());
Method[] _tmp = amethod;
CGLIB$addOrder$0$Method = amethod[0];
CGLIB$addOrder$0$Proxy = MethodProxy.create(class2, class1, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", "addOrder", "CGLIB$addOrder$0");
amethod1 = ReflectUtils.findMethods(new String[]{
"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"
}, (class2 = Class.forName("java.lang.Object")).getDeclaredMethods());
Method[] _tmp1 = amethod1;
CGLIB$equals$1$Method = amethod1[0];
CGLIB$equals$1$Proxy = MethodProxy.create(class2, class1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = amethod1[1];
CGLIB$toString$2$Proxy = MethodProxy.create(class2, class1, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = amethod1[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(class2, class1, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = amethod1[3];
CGLIB$clone$4$Proxy = MethodProxy.create(class2, class1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
}
final String CGLIB$addOrder$0(String s, String s1) {
return super.addOrder(s, s1);
}
final boolean CGLIB$equals$1(Object obj) {
return super.equals(obj);
}
final String CGLIB$toString$2() {
return super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[]) {
CGLIB$THREAD_CALLBACKS.set(acallback);
}
public final String addOrder(String paramString1, String paramString2) {
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null) {
CGLIB$BIND_CALLBACKS(this);
}
try {
MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
if (tmp17_14 != null) {
return (String) tmp17_14.intercept(this, CGLIB$addOrder$0$Method, new Object[]{paramString1, paramString2}, CGLIB$addOrder$0$Proxy);
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return super.addOrder(paramString1, paramString2);
}
public Object newInstance(Callback acallback[]) {
CGLIB$SET_THREAD_CALLBACKS(acallback);
CGLIB$SET_THREAD_CALLBACKS(null);
return new OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c();
}
public Object newInstance(Callback callback) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{
callback
});
CGLIB$SET_THREAD_CALLBACKS(null);
return new OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c();
}
public void setCallback(int i, Callback callback) {
switch (i) {
case 0: // '\0'
CGLIB$CALLBACK_0 = (MethodInterceptor) callback;
break;
}
}
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static ThreadLocal CGLIB$THREAD_CALLBACKS = null;
private static final Callback CGLIB$STATIC_CALLBACKS[] = null;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static Method CGLIB$addOrder$0$Method = null;
private static MethodProxy CGLIB$addOrder$0$Proxy = null;
private static Object[] CGLIB$emptyArgs = null;
private static Method CGLIB$equals$1$Method = null;
private static MethodProxy CGLIB$equals$1$Proxy = null;
private static Method CGLIB$toString$2$Method = null;
private static MethodProxy CGLIB$toString$2$Proxy = null;
private static Method CGLIB$hashCode$3$Method = null;
private static MethodProxy CGLIB$hashCode$3$Proxy = null;
private static Method CGLIB$clone$4$Method = null;
private static MethodProxy CGLIB$clone$4$Proxy = null;
static {
try {
CGLIB$STATICHOOK1();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c() {
CGLIB$BIND_CALLBACKS(this);
}
private void CGLIB$BIND_CALLBACKS(OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c orderServiceImpl$$EnhancerByCGLIB$$1dd3a71c) {
}
}
FastClass机制
public class MayiktFastclass {
/**
* 根据索引查找到目标方法
*
* @param index
* @param obj
* @param args
* @return
*/
public static Object invoke(int index, Object obj, Object[] args) {
OrderServiceImpl orderService = (OrderServiceImpl) obj;
switch (index) {
case 1:
return orderService.addOrder(String.valueOf(args[0]), String.valueOf(args[1]));
}
return null;
}
/**
* 根据签名索引文件
*
* @param sign
* @return
*/
public static int getIndex(String sign) {
switch (sign.hashCode()) {
case 1763340254:
return 1;
case 20:
return 2;
}
return -1;
}
public static void main(String[] args) {
System.out.println("addOrder()String,String".hashCode());
Object result = invoke(getIndex("addOrder()String,String"), new OrderServiceImpl(), new String[]{"mayikt", "meite"});
}
}
Jdk与Cglib动态代理的区别
1.Jdk动态代理利用反射技术生成匿名的代理类走InvokeHandler回调方法实现增强,同时也是一种基于接口的方式实现代理。
2.Cglib动态代理利用asm字节码技术生成一个子类覆盖其中的方法实现增强,同时采用fastClass机制对整个代理类建立索引调用目标方法
3.在Spring中如果需要被代理的对象如果实现了接口采用Jdk动态代理,没有实现接口则使用Cglib动态代理。
代理模式常见面试题
JDK动态代理与CGLIB动态代理那个效率高?
名称 只生成class(毫秒) 生成class+调用目标方法(毫秒)
Cglib代理(三个class文件) 104 133(目标方法29毫秒)
JDK动态代理(一个class) 14 30(16毫秒左右)
测试环境JDK8
Cglib代理----根据fastclass机制调用目标方法 (目标方法29毫秒)
JDK代理 反射机制调用目标方法 (16毫秒左右)
根据fastclass机制调用目标方法代理 比我们反射调用目标方法 高2倍左右
相关测试代码:
package com.mayikt;
import com.mayikt.proxy.CglibMethodInterceptor;
import com.mayikt.proxy.JdkInvocationHandler;
import com.mayikt.service.OrderService;
import com.mayikt.service.OrderServiceImpl;
import net.sf.cglib.proxy.Enhancer;
/**
* @author 余胜军
* @ClassName Test05
* @qq 644064779
* @addres www.mayikt.com
* 微信:yushengjun644
*/
public class Test05 {
public static void main(String[] args) {
// cglib 与JDK动态代理 效率测试
cglibProxy();
}
public static void jdkProxy() {
Long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
JdkInvocationHandler jdkInvocationHandler =
new JdkInvocationHandler(new OrderServiceImpl());
OrderService orderService = jdkInvocationHandler.getProxy();// 代理类
// orderService.addOrder("mayikt", 22);
}
Long end = System.currentTimeMillis();
System.out.println("总共花费时间:" + (end - start));
}
public static void cglibProxy() {
Long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
// 1.new CglibMethodInterceptor
CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
// 2.enhancer
Enhancer enhancer = new Enhancer();
//3.设置代理类 父类class
enhancer.setSuperclass(OrderServiceImpl.class);
// //4.设置回调
enhancer.setCallback(cglibMethodInterceptor);
//5.创建代理对象
OrderServiceImpl orderServiceImpl = (OrderServiceImpl) enhancer.create();
// orderServiceImpl.addOrder("mayikt", 22);
}
Long end = System.currentTimeMillis();
System.out.println("总共花费时间:" + (end - start));
}
}
JDK6 中 Jdk动态代理比CGLIB 效率低;
JDK8中CGLIB动态代理比jdk动态低5-10倍。
Spring使用的是CGLIB还是JDK动态代理
Cglib 基于 目标对象 类实现继承的形式 采用 fastclass 机制调用目标方法
JDK动态代理基于 目标对象类 实现接口 代理 采用反射机制调用目标方法
Spring判断 如果目标对象 实现接口的话 采用JDK动态代理
如果 如果目标对象 类没有实现接口的话 则采用 CGLIB代理。
JDK动态代理—实际的项目中采用JDK动态代理非常多
,程序员在编写代码的过程中 使用 接口的形式比较多。