動態代理的使用和個人理解(再看spring aop前的理解)
動態代理調用一個方法,並且對這個方法進行增強,代碼如下
代碼如下,
- //接口
1package com.enjoylearning.proxy.unknow;
2
3public interface UnknowToolsFactory {
4 void saleUnknowTools(float length);
5}
- 接口實現
1package com.enjoylearning.proxy.unknow;
2
3public class DdFactory implements UnknowToolsFactory{
4 @Override
5 public void saleUnknowTools(float length) {
6 System.out.println("根據您的需求,爲您定製了一個高度爲:\"+length+\"的Unknow模特");
7 }
8}
- 動態代理類
1package com.enjoylearning.proxy.unknow;
2
3import javax.annotation.Resource;
4import java.lang.reflect.InvocationHandler;
5import java.lang.reflect.Method;
6import java.lang.reflect.Proxy;
7
8public class LicmCompany implements InvocationHandler {
9
10 @Resource
11 private Object factory;
12
13 public Object getFactory() {
14 return factory;
15 }
16
17 public void setFactory(Object factory) {
18 this.factory = factory;
19 }
20
21 public Object getProxyInstance(){
22 return Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),this);
23 }
24
25
26 @Override
27 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
28 dosomeThingBefore();
29 Object obj = method.invoke(factory,args);
30 dosomeThingEnd();
31 return obj;
32 }
33
34 //售前服務
35 private void dosomeThingEnd() {
36 System.out.println("精美包裝,快遞一條龍服務!");
37 }
38
39 //售後服務
40 private void dosomeThingBefore() {
41 System.out.println("根據您的需求,進行市場調研和產品分析!");
42 }
43}
- 測試類,普通的main方法
1 UnknowToolsFactory unknowToolsFactory = new DdFactory();
2 LicmCompany licmCompany = new LicmCompany();
3 licmCompany.setFactory(unknowToolsFactory);
4 UnknowToolsFactory licm2 = (UnknowToolsFactory)licmCompany.getProxyInstance();
5 licm2.saleUnknowTools(1.2f);
- 附一個工具類,動態生成的二進制字節碼保存到硬盤中
1package com.enjoylearning.proxy.utils;
2
3import java.io.FileOutputStream;
4import java.io.IOException;
5import java.lang.reflect.Proxy;
6import sun.misc.ProxyGenerator;
7
8public class ProxyUtils {
9
10 /*
11 * 將根據類信息 動態生成的二進制字節碼保存到硬盤中, 默認的是clazz目錄下 params :clazz 需要生成動態代理類的類
12 * proxyName : 爲動態生成的代理類的名稱
13 */
14 public static void generateClassFile(Class clazz, String proxyName) {
15
16
17 // 根據類信息和提供的代理類名稱,生成字節碼
18 byte[] classFile = ProxyGenerator.generateProxyClass(proxyName,
19 new Class[]{clazz});
20
21 String paths = clazz.getResource(".").getPath();
22 System.out.println(paths);
23 FileOutputStream out = null;
24
25 try {
26 // 保留到硬盤中
27 out = new FileOutputStream(paths + proxyName + ".class");
28// out = new FileOutputStream("C:/a.class");
29 out.write(classFile);
30 out.flush();
31 } catch (Exception e) {
32 e.printStackTrace();
33 } finally {
34 try {
35 out.close();
36 } catch (IOException e) {
37 e.printStackTrace();
38 }
39 }
40 }
41
42}
需要注意的幾個方法
- 代碼結構,需要一個接口,實現類,實現invocationhandler的代理類
- 代理類中的public Object invoke(Object proxy, Method method, Object[] args) 的三個參數,
- 代理的真實對象(本文中的Ddfactory)
- 調用的真實方法 (saleUnknowTools)
- 調用的真實方法傳入的參數 (licm2.saleUnknowTools(1.2f))
- 一般在invoke中,會對執行方法進行增強,比如method,invoke前後加入新的方法
- proxy 這個類深入說一下
- Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods. 動態創建一個代理類對象
- 這個類最常用的是 public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
- 類加載器,由那個類加載器對象對生成的代理類進行加載,一般爲出入的實現類的接口對象(UnknowToolsFactory,一般爲factory.getclass.getclassloader)
- 接口的實現類 factory.getclass.getinterfaces()
- 爲實現invacationhandler的類