合肥制作网站的公司简介,新公司如何做推广,苏宁易购电商网站建设需求分析,国外的自建网站怎么做本文主要介绍CGLib和JDK动态代理的使用#xff0c;不对源码进行深入分析。代码可直接复制使用。 类型 机制 回调方式 适用场景 效率 JDK动态代理 委托机制。代理类和目标类都实现了同样的接口。InvocationHandler持有目标类。代理类委托InvocationHandler去调用目标类原…本文主要介绍CGLib和JDK动态代理的使用不对源码进行深入分析。代码可直接复制使用。 类型 机制 回调方式 适用场景 效率 JDK动态代理 委托机制。代理类和目标类都实现了同样的接口。InvocationHandler持有目标类。代理类委托InvocationHandler去调用目标类原始方法 反射 目标类实现接口 反射调用稍慢。 CGLIB动态代理 继承机制。代理类继承了目标类并重写了目标方法通过回调函数MethodInterceptor调用父类方法执行原始逻辑(底层使用到ASM技术操作字节码生成代理类) 通过FastClass方法索引调用 非final类非final方法 第一次调用因为要生成多个Class对象较]DK慢但是调用时方法索引较反射方式快
代码框架 类UserInterface
package com.cocoa.dao;public interface UserInterface {public void test();
}类UserService
package com.cocoa.dao;public class UserService implements UserInterface{Overridepublic void test() {System.out.println(UserService test() -- print);}
}类CGLIBDemo
method.invoke()使用的还是反射机制但是methodProxy.invoke使用的不是反射而是FastClass机制通过建立代理类的索引快速执行代理的方法。所以比JDK快
MethodIntercept的入参
o目标对象的实例被代理的对象
method被代理的方法
objects方法调用时的入参
methodProxy用于调用原始方法的代理。
package com.cocoa.enhancer;import com.cocoa.dao.UserService;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CGLIBDemo {public static void Main(String[] args) {// 动态代理生成的字节码存储到本地System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, com.cocoa.enhancer);final UserService target new UserService();// 增强器Enhancer enhancer new Enhancer();// enhancer.setUseCache(false);// 使用缓存// 设置代理的类enhancer.setSuperclass(UserService.class);// 设置代理逻辑enhancer.setCallback(new MethodInterceptor() {Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {if (method.getName().equals(test)){System.out.println(before...);method.invoke(target, objects);System.out.println(after...);}return null;}});// 使用代理类UserService userService (UserService) enhancer.create();// create会将第一次产生的代理类缓存下来userService.test();}
}要避免使用method.invoke()应该使用methodProxy。
类CGLIBDemo1
使用methodProxy.invoke执行方法(通过FastCLass索引机制)
methodProxy.invoke(target, objects);// test() 正常运行直接执行代理方法
methodProxy.invoke(o, objects);// o 表示代理对象这样会导致死循环
methodProxy.invokeSuper(target, objects);// CGLIB$test$4() 因为target中没有代理对象的方法
methodProxy.invokeSuper(o, objects);// CGLIB$test$4() 执行代理对象o中的test方法 正常运行
package com.cocoa.enhancer;import com.cocoa.dao.UserService;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** MethodProxy的使用*/
public class CGLIBDemo1 {public static void main(String[] args) {System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, com.cocoa.enhancer);final UserService target new UserService();// 增强器Enhancer enhancer new Enhancer();// enhancer.setUseCache(false);// 使用缓存// 设置代理的类enhancer.setSuperclass(UserService.class);// 设置代理逻辑enhancer.setCallback(new MethodInterceptor() {Override// o代理对象 objects入参 method被代理的方法 methodProxy代理的方法public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {if (method.getName().equals(test)){System.out.println(before...);// MethodProxy 表示方法代理代理了两个方法 test()
// methodProxy.invoke(target, objects);// test() 可用
// methodProxy.invoke(o, objects);// o 表示代理对象这样会导致死循环
// methodProxy.invokeSuper(target, objects);// CGLIB$test$4() 因为target中没有代理对象的方法methodProxy.invokeSuper(o, objects);// CGLIB$test$4() 执行代理对象o中的test方法 可用System.out.println(after...);}return null;}});// 使用代理类UserService userService (UserService) enhancer.create();// create会将第一次产生的代理类缓存下来userService.test();}
}类mainInterface
package com.cocoa.enhancer;import com.cocoa.dao.UserInterface;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** CGLIB 可以代理接口*/
public class mainInterface {public static void main(String[] args) {Enhancer enhancer new Enhancer();// 设置代理的接口enhancer.setSuperclass(UserInterface.class);// 设置代理逻辑enhancer.setCallback(new MethodInterceptor() {Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(切面逻辑...);return null;}});// 使用代理类UserInterface userInterface (UserInterface) enhancer.create();userInterface.test();}
}类JDKDemo
使用proxy.newProxyInstance方法直接构造代理类入参有
1)真实对象的类加载器
2)真实对象实现的接口
3)代理类需要实现InvocationHandler接口重写Invoke方法。
invoke方法的入参
参数1用Proxy.newProxyInstance方法产生的真实对象注意参数1并不显式地出现在方法体内
参数2要调用的目标方法
参数3目标方法中的参数一般是 Object[ ] args。
package com.cocoa.jdkProxy;import com.cocoa.dao.UserInterface;
import com.cocoa.dao.UserService;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JDKDemo {public static void main(String[] args) {// Proxy.newproxyInstance// 类加载器、代理的接口、new InvocationHandlerUserService target new UserService();UserInterface userInterface (UserInterface) Proxy.newProxyInstance(JDKDemo.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(test);method.invoke(target, args);return null;}});userInterface.test();}
}ASM技术尝鲜
通过ASM字节码技术可以生成一个类。执行下面的代码就可以生成下图中的类。 package com.cocoa.asmDemo;import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;/*** ASM 尝鲜使用*/
public class ASMDemo {public static void main(String[] args) throws IOException {ClassWriter classWriter new ClassWriter(0);// 通过visit 方法确定类的头部信息classWriter.visit(Opcodes.V1_8,// java版本Opcodes.ACC_PUBLIC,// 类修饰符Person, // 类的全限定名null, java/lang/Object, null );// 创建构造函数MethodVisitor mv classWriter.visitMethod(Opcodes.ACC_PUBLIC, init, ()V, null, null);mv.visitCode();mv.visitVarInsn(Opcodes.AALOAD, 0);// 字节码指令mv.visitMethodInsn(Opcodes.INVOKESPECIAL, java/lang/Object, init, ()V);mv.visitInsn(Opcodes.RETURN);mv.visitMaxs(1,1);mv.visitEnd();// 定义test方法MethodVisitor methodVisitor classWriter.visitMethod(Opcodes.ACC_PUBLIC, test, ()V, null, null);methodVisitor.visitCode();methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, java/lang/System, out, Ljava/io/PrintStream;);methodVisitor.visitLdcInsn(hello zhouyu);methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, java/io/PrintStream,println,(Ljava/lang/string;)V);methodVisitor.visitInsn(Opcodes.RETURN);methodVisitor.visitMaxs(2,2);methodVisitor.visitEnd();classWriter.visitEnd();// 使classWriter类已经完成// 将classWriter转换成字节数组写到文件里面大byte[] data classWriter.toByteArray();File file new File( E:\\java_shicao\\DynamicProxyDemo\\src\\main\\java\\People.class);FileOutputStream fout new FileOutputStream(file);fout.write(data);fout.close();}
}