Java學習路線-32:ClassLoader類加載器反射與代理設計模式
第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 引入
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
建議:基于接口的設計比較合理
Java
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。