Java学习路线-32:ClassLoader类加载器反射与代理设计模式

举报
彭世瑜 发表于 2021/08/13 23:34:45 2021/08/13
【摘要】 第25 章 : ClassLoader类加载器 115 ClassLoader类加载器简介 系统环境变量 CLASSPATH JVM -> ClassLoader -> CLASSPATH -> .class 1 加载器,由上至下执行 Bootstrap 系统类加载器 PlatformClassLoader 平台类加载器 AppClass...

第25 章 : ClassLoader类加载器

115 ClassLoader类加载器简介

系统环境变量 CLASSPATH

JVM -> ClassLoader -> CLASSPATH -> .class

  
 
  • 1

加载器,由上至下执行

Bootstrap 系统类加载器

PlatformClassLoader 平台类加载器

AppClassLoader 应用程序加载器

自定义类加载器(磁盘、网络)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

系统类加载器都是根据CLASSPATH路径查找类加载

应用场景:
客户端动态更新服务器端的代码

Java类加载器:双亲加载机制
为了保证系统安全性,开发者自定义类与系统类重名,不会被加载

/demo/Person.java

public class Person { public void sayHello(){ System.out.println("hello"); }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

MyClassLoader.java

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class MyClassLoader extends ClassLoader { private static final String PERSON_CLASS_PATH = "/demo" + File.separator + "Person.class"; public Class<?> loadMyClass(String className) throws IOException { byte[] data = this.loadClassData(); if (data != null) { return super.defineClass(className, data, 0, data.length); } return null; } public byte[] loadClassData() throws IOException { InputStream input = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 将数据加载到内存 byte[] data = null; byte[] temp = new byte[1024]; int len = 0; try { input = new FileInputStream(PERSON_CLASS_PATH); while ((len = input.read(temp)) != -1) { bos.write(temp, 0, len); } // 读取所有的字节 data = bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { if (input != null) { input.close(); } if (bos != null) { bos.close(); } } return data; }

}


class Demo { public static void main(String[] args) throws Exception{ MyClassLoader loader = new MyClassLoader(); Class<?> cls = loader.loadMyClass("Person"); Object obj = cls.getDeclaredConstructor().newInstance(); Method method = cls.getDeclaredMethod("sayHello"); method.invoke(obj); // hello }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

第26 章 : 反射与代理设计模式

117 静态代理设计模式

传统代理设计
必须有接口

标准的代理设计


// 接口标准
interface IMessage { void send();
}

// 业务实现类
class MessageImpl implements IMessage { @Override public void send() { System.out.println("发送"); }
}

// 代理类
class MessageProxy implements IMessage { private IMessage message; public MessageProxy(IMessage message) { this.message = message; } @Override public void send() { if (this.isConnect()) { this.message.send(); } } public void close() { } public boolean isConnect() { return true; }
}

class Demo { public static void main(String[] args) { IMessage message = new MessageProxy(new MessageImpl()); message.send(); }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

客户端和接口子类产生了耦合
最好引入工厂设计模式进行代理对象获取

静态代理类:
一个代理类只为一个接口服务

118 动态代理设计模式

最好的做法是为所有功能一致的业务操作接口提供统一的代理处理操作

不管是动态代理类还是静态代理类都一定要接收真实业务实现子类对象

代码实现

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 接口标准
interface IMessage { void send();
}

// 业务实现类
class MessageImpl implements IMessage { @Override public void send() { System.out.println("发送"); }
}


// 动态代理类
class MyProxy implements InvocationHandler{ private Object target; // 保存真实业务对象 // 真实业务对象与代理业务对象之间的绑定 public Object bind(Object target){ this.target = target; Class cls = target.getClass(); return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; if (this.isConnect()) { obj = method.invoke(this.target, args); this.close(); } return obj; } public void close() { } public boolean isConnect() { return true; }
}

class Demo { public static void main(String[] args) { IMessage message =(IMessage)new MyProxy().bind(new MessageImpl()); message.send(); }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

119 CGLIB实现代理设计模式

如果要实现代理设计模式,那么一定是基于接口的应用
CGLIB开发包实现基于类的代理设计模式
Code Generation Library

pom.xml 引入

<dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
</dependencies>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码实现

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

// 业务实现类
class Message { public void send() { System.out.println("发送"); }
}

// 动态代理类

class MyProxy implements MethodInterceptor { private Object target; // 保存真实业务对象 // 真实业务对象与代理业务对象之间的绑定 public MyProxy(Object target) { this.target = target; } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; if (this.isConnect()) { obj = method.invoke(this.target, args); this.close(); } return obj; } public void close() { } public boolean isConnect() { return true; }
}

class Demo { public static void main(String[] args) { Message message = new Message(); // 真实主体 Enhancer enhancer = new Enhancer(); // 负责代理操作的程序类 enhancer.setSuperclass(message.getClass()); // 假定一个父类 enhancer.setCallback(new MyProxy(message)); Message proxyMessage = (Message) enhancer.create(); proxyMessage.send(); }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

建议:基于接口的设计比较合理

文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。

原文链接:pengshiyu.blog.csdn.net/article/details/103789416

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。