内容简介:代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。符合开闭原则。代理模式属于结构型 模式,有静态代理和动态代理。需求:现在我们需要根据类型来分别把数据上传到不同Ftp服务。动态代理有以下特点:
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。符合开闭原则。代理模式属于结构型 模式,有静态代理和动态代理。
静态代理
需求:现在我们需要根据类型来分别把数据上传到不同Ftp服务。
/**
* 数据的模型类
*/
public static class Data {
private Integer type;
private String name;
private String sex;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public static interface IFTPService {
void upload(Data data);
}
public static class FTPService implements IFTPService {
@Override
public void upload(Data data) {
System.out.println("Data{" +
"type=" + data.getType() +
", name='" + data.getName() + '\'' +
", sex='" + data.getSex() + '\'' +
'}');
}
}
public static class FTPServiceStaticProxy implements IFTPService {
private IFTPService ftpService;
// 静态代理 构造注入的方式赋值
public FTPServiceStaticProxy(IFTPService ftpService) {
this.ftpService = ftpService;
}
@Override
public void upload(Data data) {
before();
if (data.getType() % 2 == 0) {
System.out.println("上传到服务器 1");
ftpService.upload(data);
} else {
System.out.println("上传到服务器 2");
ftpService.upload(data);
}
after();
}
private void before(){
System.out.println("Proxy before method.");
}
private void after(){
System.out.println("Proxy after method.");
}
}
public static void main(String[] args) {
Data data = new Data();
data.setName("Name Zhuang San");
data.setSex("男");
data.setType(1);
new FTPServiceStaticProxy(new FTPService()).upload(data);
Data data2 = new Data();
data.setName("Name Wan Wu");
data.setSex("男");
data.setType(2);
new FTPServiceStaticProxy(new FTPService()).upload(data);
}
复制代码
动态代理
动态代理有以下特点:
- 代理对象,不需要实现接口
- 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
- 动态代理也叫做: JDK代理,接口代理
JDK 实现方式
/**
* 数据的模型类
*/
public static class Data {
private Integer type;
private String name;
private String sex;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public static interface IFTPService {
void upload(Data data);
}
public static class FTPService implements IFTPService {
@Override
public void upload(Data data) {
System.out.println("Data{" +
"type=" + data.getType() +
", name='" + data.getName() + '\'' +
", sex='" + data.getSex() + '\'' +
'}');
}
}
public static class JDKProxyFTPService implements InvocationHandler {
private Object target;
public Object upload(Object target) {
this.target = target;
Class<?> clazz = target.getClass();
// 如何实现的代理?
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 只让 upload 方法进入
if (!"upload".equals(method.getName())) return method.invoke(target, args);
before(args[0]);
Object r = method.invoke(target, args);
after();
return r;
}
private void before(Object data){
System.out.println("Proxy before method.");
if (data instanceof Data) { // 判断是否属于 -- Data 模型
Data d = (Data) data;
if (d.getType() % 2 == 0)
System.out.println("上传到服务器 1");
else
System.out.println("上传到服务器 2");
}
}
private void after(){
System.out.println("Proxy after method.");
}
}
public static void main(String[] args) {
IFTPService ftpService = (IFTPService) new JDKProxyFTPService().upload(new FTPService());
Data data = new Data();
data.setName("Name Zhuang San");
data.setSex("男");
data.setType(1);
ftpService.upload(data);
}
复制代码
Proxy 是如何实现的呢?
我们都知道 JDK Proxy 采用字节重组,重新生的对象来替代原始的对象以达到动态代理的目的。JDK Proxy 生成对象的步骤如下:
- 拿到被代理对象的引用,并且获取到它的所有的接口,反射获取。
- JDK Proxy 类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口。
- 动态生成 Java 代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)。
- 编译新生成的 Java 代码.class。
- 再重新加载到 JVM 中运行。
public static void main(String[] args) throws IOException {
//通过反编译 工具 可以查看源代码
byte [] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{IFTPService.class});
FileOutputStream os = new FileOutputStream("E://$Proxy0.class");
os.write(bytes);
os.close();
}
复制代码
使用反编译工具,得到java代码如下:
package com.reape.design.pattern.proxy;
import java.lang.reflect.*;
import com.reape.design.pattern.proxy.*;
// 继承了Proxy类 接口我们的 JDKIFTPService
public final class $Proxy0 extends Proxy implements JDKIFTPService
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(final InvocationHandler invocationHandler) {
super(invocationHandler);
}
// 重写了 toString hashCode equals 指向了原来的地址
public final boolean equals(final Object o) {
try {
return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
}
catch (Error | RuntimeException error) {
throw new Error();
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void upload(final JDKData jdkData) {
try {
super.h.invoke(this, $Proxy0.m3, new Object[] { jdkData });
}
catch (Error | RuntimeException error) {
throw new Error();
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String toString() {
try {
return (String)super.h.invoke(this, $Proxy0.m2, null);
}
catch (Error | RuntimeException error) {
throw new Error();
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final int hashCode() {
try {
return (int)super.h.invoke(this, $Proxy0.m0, null);
}
catch (Error | RuntimeException error) {
throw new Error();
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
static {
try {
$Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
$Proxy0.m3 = Class.forName("com.reape.design.pattern.proxy.JDKIFTPService").getMethod("upload", Class.forName("com.reape.design.pattern.proxy.JDKData"));
$Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
$Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
}
catch (NoSuchMethodException ex) {
throw new NoSuchMethodError(ex.getMessage());
}
catch (ClassNotFoundException ex2) {
throw new NoClassDefFoundError(ex2.getMessage());
}
}
}
复制代码
手写动态代理
// 1. ClassLoader 自定义
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MyClassLoader extends ClassLoader{
private File classPathFile;
public MyClassLoader(){
String classPath = MyClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = MyClassLoader.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(null != in){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
}
// 2. 动态代理实现的接口类
import java.lang.reflect.Method;
/**
* 动态代理实现的接口类
*/
public interface MyInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
3. 生成java文件编译为class写入jvm,动态代理
/**
* 用来生成源代码的工具类
*/
public class MyProxy {
private static final String ln = "\r\n";
private static final String t = "\t";
public static Object newProxyInstance(MyClassLoader classLoader,
Class<?> [] interfaces,
MyInvocationHandler h){
try {
// 1.动态生成源代码文件
String src = generateSrc(interfaces);
//2、Java 文件输出磁盘
String filePath = MyProxy.class.getResource("").getPath();
System.out.println(filePath);
File f = new File(filePath + "$Proxy0.java");
FileWriter fw = null;
fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
//3、把生成的.java 文件编译成.class 文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null);
Iterable iterable = manage.getJavaFileObjects(f);
JavaCompiler.CompilationTask task =
compiler.getTask(null,manage,null,null,null, iterable);
task.call();
manage.close();
//4、编译生成的.class 文件加载到 JVM 中来
Class<Object> proxyClass = (Class<Object>) classLoader.findClass("$Proxy0");
Constructor<Object> c = proxyClass.getConstructor(MyInvocationHandler.class);
// f.delete();
//5、返回字节码重组以后的新的代理对象
return c.newInstance(h);
} catch (IOException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class<?>[] interfaces){
// interfaces ---> 需要实现的接口的类
StringBuilder sb = new StringBuilder();
sb.append("package com.reape.design.pattern.proxy.handwriting;" + ln);
sb.append("import java.lang.reflect.*;" + ln);
sb.append("public class $Proxy0 implements").append(interfacesToString(interfaces));
sb.append(" {").append(ln);
sb.append(t + "private com.reape.design.pattern.proxy.handwriting.MyInvocationHandler h;" + ln);
sb.append(t + "public $Proxy0(com.reape.design.pattern.proxy.handwriting.MyInvocationHandler h) { " + ln);
sb.append(t + t + "this.h = h;" + ln);
sb.append(t + "}" + ln);
for (Class<?> anInterface : interfaces) {
for (Method m : anInterface.getMethods()) {
Class<?>[] params = m.getParameterTypes();
Class<?> result = m.getReturnType();
sb.append(t + "public final ")
.append(resultToString(result))
.append(" ")
.append(m.getName())
.append("(")
.append(paramsToString(params))
.append(") {").append(ln);
sb.append(t + t + "try {" + ln);
sb.append(t + t + t)
.append(returnToString(result))
.append("h.invoke(this, " + "Class.forName(\"")
// .append(anInterface.getName())
.append("com.reape.design.pattern.proxy.JDKFTPService")
.append("\")")
.append(".getMethod(").append("\"").append(m.getName()).append("\"").append(", ")
.append(paramsFormNameToString(params))
.append(")").append(", new Object[]{ p0 });").append(ln);
sb.append(t + t + "}" + ln);
sb.append(t + t + "catch(Error | RuntimeException error) { error.printStackTrace();" + ln);
sb.append(t + t + t + "throw new Error();" + ln);
sb.append(t + t + "}" + ln);
sb.append(t + t + "catch (Throwable t) {" + ln);
sb.append(t + t + t + "throw new UndeclaredThrowableException(t);" + ln);
sb.append(t + t + "}" + ln);
sb.append(t + "}" + ln);
}
}
sb.append("}" + ln);
return sb.toString();
}
/**
* 接口类数组转 String
* @param interfaces 接口类数组
* @return 字符串
*/
private static String interfacesToString(Class<?>[] interfaces) {
if (interfaces.length < 1) return "";
StringBuilder sb = new StringBuilder();
for (Class<?> anInterface : interfaces) {
sb.append(" ").append(anInterface.getName()).append(",");
}
return sb.substring(0, sb.length() - 1);
}
private static String paramsToString(Class<?>[] params) {
if (params.length < 1) return "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.length; i++) {
sb.append(params[i].getName()).append(" ").append("p").append(i).append(", ");
}
return sb.substring(0, sb.length() - 2);
}
private static String paramsFormNameToString(Class<?>[] params) {
if (params.length < 1) return "";
StringBuilder sb = new StringBuilder();
for (Class<?> param : params) {
sb.append("Class.forName(\"").append(param.getName()).append("\"), ");
}
return sb.substring(0, sb.length() - 2);
}
private static String resultToString(Class<?> result) {
String name = result.getName();
return "void".equals(name) ? "void" : name;
}
private static String returnToString(Class<?> result) {
String name = result.getName();
return "void".equals(name) ? "" : "return (" + name + ") ";
}
}
// 4.测试
public class Test implements MyInvocationHandler {
private Object target;
public Object get(Object target) {
this.target = target;
Class<?> clazz = target.getClass();
return MyProxy.newProxyInstance(new MyClassLoader(), clazz.getInterfaces(), this);
}
private void before(Object data){
System.out.println(data);
System.out.println("Proxy before method.");
}
private void after(){
System.out.println("Proxy after method.");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 只让 upload 方法进入
if (!"upload".equals(method.getName())) return method.invoke(target, args);
before(args[0]);
Object r = method.invoke(target, args);
after();
return r;
}
public static void main(String[] args) {
JDKIFTPService ftpService = (JDKIFTPService) new Test().get(new JDKFTPService());
JDKData data = new JDKData();
data.setName("Name Zhuang San");
data.setSex("男");
data.setType(1);
ftpService.upload(data);
}
}
// 上面的代码写考虑的不是很完整
// 有很多判断的地方没有判断以及重写 toString ,equals 等
// java的代理是编译为class文件然后写入的到jvm节约的了内存消耗,但是跟cglib对比还是差很远
// cglib是字节码操作
复制代码
CGLib实现
// 导入jar包
// 1. asm.jar
// 2. cglib.jar
public class JDKData {
private Integer type;
private String name;
private String sex;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public class JDKFTPService implements JDKIFTPService {
@Override
public void upload(JDKData data) {
System.out.println("Data{" +
"type=" + data.getType() +
", name='" + data.getName() + '\'' +
", sex='" + data.getSex() + '\'' +
'}');
}
}
public class CglibJDK implements MethodInterceptor {
public Object getInstance(Class<?> clazz) throws Exception{
Enhancer enhancer = new Enhancer();
//要把哪个设置为即将生成的新类父类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//业务的增强
before(objects[0]);
Object obj = methodProxy.invokeSuper(o,objects);
after();
return obj;
}
private void before(Object data){
System.out.println("Proxy before method.");
System.out.println(data);
if (data instanceof JDKData) { // 判断是否属于 -- Data 模型
JDKData d = (JDKData) data;
if (d.getType() % 2 == 0)
System.out.println("上传到服务器 1");
else
System.out.println("上传到服务器 2");
}
}
private void after(){
System.out.println("Proxy after method.");
}
}
// 测试
public static void main(String[] args) {
try {
JDKFTPService obj = (JDKFTPService) new CglibJDK().getInstance(JDKFTPService.class);
JDKData data = new JDKData();
data.setName("Name Zhuang San");
data.setSex("男");
data.setType(1);
obj.upload(data);
} catch (Exception e) {
e.printStackTrace();
}
}
// 编译得到class文件
package com.reape.design.pattern.proxy.cglib;
import net.sf.cglib.reflect.*;
import net.sf.cglib.core.*;
import net.sf.cglib.proxy.*;
import java.lang.reflect.*;
public class JDKFTPService$$EnhancerByCGLIB$$5a7831ef$$FastClassByCGLIB$$5a694231 extends FastClass
{
public JDKFTPService$$EnhancerByCGLIB$$5a7831ef$$FastClassByCGLIB$$5a694231(final Class clazz) {
super(clazz);
}
public int getIndex(final Signature signature) {
final String string = signature.toString();
switch (string.hashCode()) {
case -2055565910: {
if (string.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 12;
}
break;
}
case -1882565338: {
if (string.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
return 15;
}
break;
}
case -1457535688: {
if (string.equals("CGLIB$STATICHOOK1()V")) {
return 19;
}
break;
}
case -1411842725: {
if (string.equals("CGLIB$hashCode$3()I")) {
return 18;
}
break;
}
case -894172689: {
if (string.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 6;
}
break;
}
case -623122092: {
if (string.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
return 20;
}
break;
}
case -508378822: {
if (string.equals("clone()Ljava/lang/Object;")) {
return 3;
}
break;
}
case -419626537: {
if (string.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
return 11;
}
break;
}
case 560567118: {
if (string.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
return 7;
}
break;
}
case 773140094: {
if (string.equals("CGLIB$upload$0(Lcom/reape/design/pattern/proxy/cglib/JDKData;)V")) {
return 14;
}
break;
}
case 811063227: {
if (string.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 5;
}
break;
}
case 840180909: {
if (string.equals("upload(Lcom/reape/design/pattern/proxy/cglib/JDKData;)V")) {
return 8;
}
break;
}
case 973717575: {
if (string.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
return 10;
}
break;
}
case 1221173700: {
if (string.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 4;
}
break;
}
case 1230699260: {
if (string.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
return 9;
}
break;
}
case 1306468936: {
if (string.equals("CGLIB$toString$2()Ljava/lang/String;")) {
return 16;
}
break;
}
case 1584330438: {
if (string.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 13;
}
break;
}
case 1800494055: {
if (string.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
return 17;
}
break;
}
case 1826985398: {
if (string.equals("equals(Ljava/lang/Object;)Z")) {
return 0;
}
break;
}
case 1913648695: {
if (string.equals("toString()Ljava/lang/String;")) {
return 1;
}
break;
}
case 1984935277: {
if (string.equals("hashCode()I")) {
return 2;
}
break;
}
}
return -1;
}
public int getIndex(final String s, final Class[] array) {
Label_1103: {
switch (s.hashCode()) {
case -1776922004: {
if (!s.equals("toString")) {
break;
}
switch (array.length) {
case 0: {
return 1;
}
default: {
break Label_1103;
}
}
break;
}
case -1295482945: {
if (!s.equals("equals")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("java.lang.Object")) {
return 0;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case -1053468136: {
if (!s.equals("getCallbacks")) {
break;
}
switch (array.length) {
case 0: {
return 10;
}
default: {
break Label_1103;
}
}
break;
}
case -838595071: {
if (!s.equals("upload")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("com.reape.design.pattern.proxy.cglib.JDKData")) {
return 8;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case -124978609: {
if (!s.equals("CGLIB$equals$1")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("java.lang.Object")) {
return 15;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case -60403779: {
if (!s.equals("CGLIB$SET_STATIC_CALLBACKS")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 13;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case -29025555: {
if (!s.equals("CGLIB$hashCode$3")) {
break;
}
switch (array.length) {
case 0: {
return 18;
}
default: {
break Label_1103;
}
}
break;
}
case 85179481: {
if (!s.equals("CGLIB$SET_THREAD_CALLBACKS")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 12;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 94756189: {
if (!s.equals("clone")) {
break;
}
switch (array.length) {
case 0: {
return 3;
}
default: {
break Label_1103;
}
}
break;
}
case 147696667: {
if (!s.equals("hashCode")) {
break;
}
switch (array.length) {
case 0: {
return 2;
}
default: {
break Label_1103;
}
}
break;
}
case 161998109: {
if (!s.equals("CGLIB$STATICHOOK1")) {
break;
}
switch (array.length) {
case 0: {
return 19;
}
default: {
break Label_1103;
}
}
break;
}
case 495524492: {
if (!s.equals("setCallbacks")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 11;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 857604112: {
if (!s.equals("CGLIB$upload$0")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("com.reape.design.pattern.proxy.cglib.JDKData")) {
return 14;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 1154623345: {
if (!s.equals("CGLIB$findMethodProxy")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("net.sf.cglib.core.Signature")) {
return 20;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 1543336189: {
if (!s.equals("CGLIB$toString$2")) {
break;
}
switch (array.length) {
case 0: {
return 16;
}
default: {
break Label_1103;
}
}
break;
}
case 1811874389: {
if (!s.equals("newInstance")) {
break;
}
switch (array.length) {
case 1: {
final String name = array[0].getName();
switch (name.hashCode()) {
case -845341380: {
if (name.equals("net.sf.cglib.proxy.Callback")) {
return 6;
}
break;
}
case 1730110032: {
if (name.equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 4;
}
break;
}
}
break Label_1103;
}
case 3: {
if (array[0].getName().equals("[Ljava.lang.Class;") && array[1].getName().equals("[Ljava.lang.Object;") && array[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 5;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 1817099975: {
if (!s.equals("setCallback")) {
break;
}
switch (array.length) {
case 2: {
if (array[0].getName().equals("int") && array[1].getName().equals("net.sf.cglib.proxy.Callback")) {
return 7;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 1905679803: {
if (!s.equals("getCallback")) {
break;
}
switch (array.length) {
case 1: {
if (array[0].getName().equals("int")) {
return 9;
}
break Label_1103;
}
default: {
break Label_1103;
}
}
break;
}
case 1951977610: {
if (!s.equals("CGLIB$clone$4")) {
break;
}
switch (array.length) {
case 0: {
return 17;
}
default: {
break Label_1103;
}
}
break;
}
}
}
return -1;
}
public int getIndex(final Class[] array) {
switch (array.length) {
case 0: {
return 0;
}
default: {
return -1;
}
}
}
public Object invoke(final int n, final Object o, final Object[] array) throws InvocationTargetException {
final JDKFTPService$$EnhancerByCGLIB$$5a7831ef jdkftpService$$EnhancerByCGLIB$$5a7831ef = (JDKFTPService$$EnhancerByCGLIB$$5a7831ef)o;
try {
switch (n) {
case 0: {
return new Boolean(jdkftpService$$EnhancerByCGLIB$$5a7831ef.equals(array[0]));
}
case 1: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.toString();
}
case 2: {
return new Integer(jdkftpService$$EnhancerByCGLIB$$5a7831ef.hashCode());
}
case 3: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.clone();
}
case 4: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Callback[])array[0]);
}
case 5: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Class[])array[0], (Object[])array[1], (Callback[])array[2]);
}
case 6: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Callback)array[0]);
}
case 7: {
jdkftpService$$EnhancerByCGLIB$$5a7831ef.setCallback(((Number)array[0]).intValue(), (Callback)array[1]);
return null;
}
case 8: {
jdkftpService$$EnhancerByCGLIB$$5a7831ef.upload((JDKData)array[0]);
return null;
}
case 9: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.getCallback(((Number)array[0]).intValue());
}
case 10: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.getCallbacks();
}
case 11: {
jdkftpService$$EnhancerByCGLIB$$5a7831ef.setCallbacks((Callback[])array[0]);
return null;
}
case 12: {
JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$SET_THREAD_CALLBACKS((Callback[])array[0]);
return null;
}
case 13: {
JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$SET_STATIC_CALLBACKS((Callback[])array[0]);
return null;
}
case 14: {
jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$upload$0((JDKData)array[0]);
return null;
}
case 15: {
return new Boolean(jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$equals$1(array[0]));
}
case 16: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$toString$2();
}
case 17: {
return jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$clone$4();
}
case 18: {
return new Integer(jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$hashCode$3());
}
case 19: {
JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$STATICHOOK1();
return null;
}
case 20: {
return JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$findMethodProxy((Signature)array[0]);
}
}
}
catch (Throwable t) {
throw new InvocationTargetException(t);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(final int n, final Object[] array) throws InvocationTargetException {
try {
switch (n) {
case 0: {
return new JDKFTPService$$EnhancerByCGLIB$$5a7831ef();
}
}
}
catch (Throwable t) {
throw new InvocationTargetException(t);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 20;
}
}
// 里面使用 extends FastClass
// 子类重写父类的方法
// 父类方法不能是final
复制代码
CGLib 和 JDK 动态代理对比
- JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
- JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
- JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。
静态代理和动态的本质区别
- 静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步 新增,违背开闭原则。
- 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开 闭原则。
- 若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成, 无需修改代理类的代码。 代理模式的优缺点 使用代理模式具有以下几个优点:
-
代理模式能将代理对象与真实被调用的目标对象分离。
-
一定程度上降低了系统的耦合度,扩展性好。
-
可以起到保护目标对象的作用。
-
可以对目标对象的功能增强。
当然,代理模式也是有缺点的:
- 代理模式会造成系统设计中类的数量增加。
- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
- 增加了系统的复杂度。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。