Java的三種代理模式&完整源碼分析
參考資料:
博客園-Java的三種代理模式
簡書-JDK動態代理-超詳細源碼分析
[博客園-WeakCache緩存的實現機制](https://www.cnblogs.com/liuyun1995/p/8144676.html)
靜態代理
靜態代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現相同的接口或者是繼承相同父類
- 可以做到在不修改目標對象的功能前提下,對目標功能擴展
- 缺點:
- 因為代理對象需要與目標對象實現一樣的接口,所以會有很多代理類,類太多
- 同時,一旦接口增加方法,目標對象與代理對象都要維護
如何解決靜態代理中的缺點呢?答案是可以使用動態代理方式
實現靜態代理的步驟
- 定義業務接口
- 被代理類實現業務接口
- 定義代理類并實現業務接口
- 最后便可通過客戶端進行調用(這里可以理解成程序的main方法里的內容)
定義接口 UserInterface
public interface UserInterface {// 保存用戶信息void save();
}
定義接口的實現類 UserService
public class UserService implements UserInterface {@Overridepublic void save() {System.out.println("[靜態代理] 保存用戶信息");}
}
定義靜態代理 UserProxy
public class UserProxy implements UserInterface {private UserInterface userInterface;public UserProxy(UserInterface userInterface) {this.userInterface = userInterface;}/*** save 代理方法*/@Overridepublic void save() {// 調用目標方法前處理System.out.println("[靜態代理] save 開始代理...");// 調用目標方法userInterface.save();// 調用目標方法后處理System.out.println("[靜態代理] save 結束代理...");}
}
測試客戶端
public class Client {public static void main(String[] args) {// 新建目標對象UserService userService = new UserService();// 創建目標對象的代理對象UserProxy userProxy = new UserProxy(userService);// 執行代理對象userProxy.save();}
}
動態代理
Java動態代理的優勢是實現無侵入式的代碼擴展,也就是方法的增強;讓你可以在不用修改源碼的情況下,增強一些方法;在方法的前后你可以做你任何想做的事情(甚至不去執行這個方法就可以)
特點
- 在程序運行時,通過反射機制動態生成
- 動態代理類通常代理接口下的所有類
- 動態代理事先不知道要代理的是什么,只有在運行的時候才能確定
JDK動態代理
- 動態代理的調用處理程序必須事先InvocationHandler接口,及使用Proxy類中的newProxyInstance方法動態的創建代理類
- Java動態代理只能代理接口,要代理類需要使用第三方的CLIGB等類庫
問題
- 為什么JDK動態代理只能代理接口?
Proxy.java->ProxyClassFactory->apply();/** Verify that the Class object actually represents an* interface.*/
// interfaceClass 指的是 Proxy.newProxyInstance 中的 interfaces
if (!interfaceClass.isInterface()) {throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
}
注意該方法是在Proxy類中是靜態方法,且接收的三個參數依次為:
ClassLoader loader
:指定當前目標對象使用類加載器,獲取加載器的方法是固定的Class<?>[] interfaces
:目標對象實現的接口的類型,使用泛型方式確認類型InvocationHandler h
:事件處理,執行目標對象的方法時,會觸發事件處理器的方法,會把當前執行目標對象的方法作為參數傳入
實現JDK動態代理的步驟
- 創建被代理的接口和類
- 創建InvocationHandler接口的實現類,在invoke方法中實現代理邏輯
- 通過Proxy的靜態方法
newProxyInstance( ClassLoaderloader, Class[] interfaces, InvocationHandler h)
創建一個代理對象 - 使用代理對象
定義接口 UserInterface
public interface UserInterface {// 保存用戶信息void save();// 更新用戶信息void update();
}
定義接口的實現類 UserService
public class UserService implements UserInterface {@Overridepublic void save() {System.out.println("[JDK動態代理] 保存用戶信息");}@Overridepublic void update() {System.out.println("[JDK動態代理] 更新用戶信息");}
}
定義代理工廠 ProxyFactory
public class ProxyFactory {// 維護的目標對象private Object target;private Class<?> clazz;public ProxyFactory(Object target, Class<?> clazz) {this.target = target;this.clazz = clazz;}// 獲取代理對象public Object getProxyObjectByClazz() {return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{clazz},(proxy, method, args) -> {System.out.println("[JDK動態代理] save 開始代理...");System.out.println("當前線程名稱:" + Thread.currentThread().getName());String className = method.getDeclaringClass().getName();System.out.println("目標對象類名稱:" + className);String methodName = method.getName();System.out.println("目標對象方法名:" + methodName);Class<?>[] parameterTypes = method.getParameterTypes();System.out.println("目標對象參數:" + parameterTypes);// 執行目標對象并獲取返回值/該方法后面不會執行
// Object returnValue = method.invoke(target, args);System.out.println("[JDK動態代理] save 結束代理...");return null;});}/*** 獲取代理對象** @return*/public Object getProxyObjectByTarget() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),(proxy, method, args) -> {System.out.println("[JDK動態代理] save 開始代理...");System.out.println("當前線程名稱:" + Thread.currentThread().getName());String className = method.getDeclaringClass().getName();System.out.println("目標對象類名稱:" + className);String methodName = method.getName();System.out.println("目標對象方法名:" + methodName);Class<?>[] parameterTypes = method.getParameterTypes();System.out.println("目標對象參數:" + parameterTypes);// 執行目標對象并獲取返回值Object returnValue = method.invoke(target, args);System.out.println("[JDK動態代理] save 結束代理...");return returnValue;});}
}
測試客戶端
public class Client {public static void main(String[] args) {System.out.println("********************* 使用接口生成代理對象 *********************");System.out.println("當前線程:" + Thread.currentThread().getName());UserInterface proxy = (UserInterface) new ProxyFactory(null, UserInterface.class).getProxyObjectByClazz();System.out.println("代理對象類型:" + proxy.getClass());proxy.save();System.out.println("********************* 使用實現類生成代理對象 *********************");UserService userService = new UserService();System.out.println("目標對象類型:" + userService.getClass());UserInterface proxy2 = (UserInterface) new ProxyFactory(userService, null).getProxyObjectByTarget();System.out.println("代理對象類型:" + proxy2.getClass());proxy2.update();}
}
輸出結果
********************* 使用接口生成代理對象 *********************
當前線程:main
代理對象類型:class com.sun.proxy.$Proxy0
[JDK動態代理] save 開始代理...
當前線程名稱:main
目標對象類名稱:com.example.spring_boot.modules.study.proxyobject.jdkproxy.UserInterface
目標對象方法名:save
目標對象參數:[Ljava.lang.Class;@c038203
[JDK動態代理] save 結束代理...
********************* 使用實現類生成代理對象 *********************
目標對象類型:class com.example.spring_boot.modules.study.proxyobject.jdkproxy.UserService
代理對象類型:class com.sun.proxy.$Proxy0
[JDK動態代理] save 開始代理...
當前線程名稱:main
目標對象類名稱:com.example.spring_boot.modules.study.proxyobject.jdkproxy.UserInterface
目標對象方法名:update
目標對象參數:[Ljava.lang.Class;@cb5822
[JDK動態代理] 更新用戶信息
[JDK動態代理] save 結束代理...
運行結果和靜態代理一樣,說明成功了。但是,我們注意到,我們并沒有像靜態代理那樣去自己定義一個代理類,并實例化代理對象。實際上,動態代理的代理對象是在內存中的,是JDK根據我們傳入的參數生成好的。那動態代理的代理類和代理對象是怎么產生的呢?重頭戲來了,且往下看
JDK動態代理源碼分析
代理對象的入口
Proxy.java->newProxyInstance();// 1. 查找或生成指定的代理類(下面會詳細說明該部分內容)
Class<?> cl = getProxyClass0(loader, intfs);// 2. 根據Class獲取構造器
final Constructor<?> cons = cl.getConstructor(constructorParams);// 3. 返回實例化的構造器
return cons.newInstance(new Object[]{h});
詳細說說 getProxyClass0 這個方法
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {// 限定代理的接口不能超過65535個if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}// If the proxy class defined by the given loader implementing// the given interfaces exists, this will simply return the cached copy;// otherwise, it will create the proxy class via the ProxyClassFactory// 如果給定加載程序定義的代理類實現// 給定的接口存在,這只會返回緩存的副本;// 否則,它將通過proxyclassfactory創建代理類return proxyClassCache.get(loader, interfaces);
}
說明一下上面提到的 proxyClassCache
// proxyClassCache變量是在Proxy.java中的靜態變量
// 一個靜態的 proxy class 緩存對象
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());/* 那就再探究一下 WeakCache 這個類 */
final class WeakCache<K, P, V> {// Reference引用隊列private final ReferenceQueue<K> refQueue = new ReferenceQueue<>();// the key type is Object for supporting null key// 使用了二級緩存技術,key為一級緩存,value為二級緩存,key是Object類型是為了存儲nullprivate final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();// reverseMap記錄了所有代理類生成器是否可用, 這是為了實現緩存的過期機制private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap<>();// 生成二級緩存key的工廠, 這里傳入的是KeyFactoryprivate final BiFunction<K, P, ?> subKeyFactory;// 生成二級緩存value的工廠, 這里傳入的是ProxyClassFactoryprivate final BiFunction<K, P, V> valueFactory;/*** Construct an instance of {@code WeakCache}** @param subKeyFactory a function mapping a pair of* {@code (key, parameter) -> sub-key}* @param valueFactory a function mapping a pair of* {@code (key, parameter) -> value}* @throws NullPointerException if {@code subKeyFactory} or* {@code valueFactory} is null.*/// 構造器,上面初始化proxyClassCache用到的public WeakCache(BiFunction<K, P, ?> subKeyFactory,BiFunction<K, P, V> valueFactory) {this.subKeyFactory = Objects.requireNonNull(subKeyFactory);this.valueFactory = Objects.requireNonNull(valueFactory);}/*** Look-up the value through the cache. This always evaluates the* {@code subKeyFactory} function and optionally evaluates* {@code valueFactory} function if there is no entry in the cache for given* pair of (key, subKey) or the entry has already been cleared.** @param key possibly null key* @param parameter parameter used together with key to create sub-key and* value (should not be null)* @return the cached value (never null)* @throws NullPointerException if {@code parameter} passed in or* {@code sub-key} calculated by* {@code subKeyFactory} or {@code value}* calculated by {@code valueFactory} is null.*/// 這個方法我們下面詳細講public V get(K key, P parameter) {...}...
}
上面的一個小插曲,現在繼續講 WeakCache.java 中的 get 方法
// K和P就是WeakCache定義中的泛型,key是類加載器,parameter是接口類數組
public V get(K key, P parameter) {// 驗證接口類數組不為空Objects.requireNonNull(parameter);// 清除無效的緩存expungeStaleEntries();// 將ClassLoader包裝成CacheKey, 作為一級緩存的keyObject cacheKey = CacheKey.valueOf(key, refQueue);// lazily install the 2nd level valuesMap for the particular cacheKey// 獲取二級緩存ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);// 如果緩存中沒有,向緩存中放入數據if (valuesMap == null) {// CAS方式put,如果不存在則放入,存在則不放入。放入后會返回null,沒有放入會返回當前的valueConcurrentMap<Object, Supplier<V>> oldValuesMap= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());// 如果oldValuesMap有值, 說明放入失敗,也說明已經存在了,會把 valuesMap 刷新回以前存在的值if (oldValuesMap != null) {valuesMap = oldValuesMap;}}// create subKey and retrieve the possible Supplier<V> stored by that// subKey from valuesMap// 根據代理類實現的接口數組來生成二級緩存key, 分為key0, key1, key2, keyxObject subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));// 根據subKey獲取到二級緩存的值Supplier<V> supplier = valuesMap.get(subKey);Factory factory = null;// 這個循環提供了輪詢機制, 如果條件為假就繼續重試直到條件為真為止while (true) {if (supplier != null) {// supplier might be a Factory or a CacheValue<V> instance// 在這里supplier可能是一個Factory也可能會是一個CacheValue// 在這里不作判斷, 而是在Supplier實現類的get方法里面進行驗證// 下面詳細講這個方法V value = supplier.get();if (value != null) {return value;}}// else no supplier in cache// or a supplier that returned null (could be a cleared CacheValue// or a Factory that wasn't successful in installing the CacheValue)// lazily construct a Factoryif (factory == null) {// 新建一個Factory實例作為subKey對應的值factory = new Factory(key, parameter, subKey, valuesMap);}if (supplier == null) {// 到這里表明subKey沒有對應的值, 就將factory作為subKey的值放入supplier = valuesMap.putIfAbsent(subKey, factory);if (supplier == null) {// successfully installed Factory// 到這里表明成功將factory放入緩存supplier = factory;}// else retry with winning supplier} else { // 否則, 可能期間有其他線程修改了值, 那么就不再繼續給subKey賦值, 而是取出來直接用if (valuesMap.replace(subKey, supplier, factory)) {// successfully replaced// cleared CacheEntry / unsuccessful Factory// with our Factory// 成功將factory替換成新的值supplier = factory;} else {// retry with current supplier// 替換失敗, 繼續使用原先的值supplier = valuesMap.get(subKey);}}}
}
WeakCache的get方法并沒有用鎖進行同步,那它是怎樣實現線程安全的呢?因為它的所有會進行修改的成員變量都使用了ConcurrentMap,這個類是線程安全的。因此它將自身的線程安全委托給了ConcurrentMap, get方法盡可能的將同步代碼塊縮小,這樣可以有效提高WeakCache的性能。我們看到ClassLoader作為了一級緩存的key,這樣可以首先根據ClassLoader篩選一遍,因為不同ClassLoader加載的類是不同的。然后它用接口數組來生成二級緩存的key,這里它進行了一些優化,因為大部分類都是實現了一個或兩個接口,所以二級緩存key分為key0,key1,key2,keyX。key0到key2分別表示實現了0到2個接口,keyX表示實現了3個或以上的接口,事實上大部分都只會用到key1和key2。這些key的生成工廠是在Proxy類中,通過WeakCache的構造器將key工廠傳入。這里的二級緩存的值是一個Factory實例,最終代理類的值是通過Factory這個工廠來獲得的
再詳細講 supplier.get()
@Override
public synchronized V get() { // serialize access// re-check// 從二級緩存里面再獲取Supplier, 用來驗證是否是Factory本身Supplier<V> supplier = valuesMap.get(subKey);if (supplier != this) {// something changed while we were waiting:// might be that we were replaced by a CacheValue// or were removed because of failure ->// return null to signal WeakCache.get() to retry// the loop// 在這里驗證supplier是否是Factory實例本身, 如果不則返回null讓調用者繼續輪詢重試// 期間supplier可能替換成了CacheValue, 或者由于生成代理類失敗被從二級緩存中移除了return null;}// else still us (supplier == this)// create new valueV value = null;try {// 委托valueFactory去生成代理類, 這里會通過傳入的ProxyClassFactory去生成代理類// 后面詳細講 ProxyClassFactory 代理類工廠,代理對象就是在這里產生的value = Objects.requireNonNull(valueFactory.apply(key, parameter));} finally {if (value == null) { // remove us on failure// 如果生成代理類失敗, 就將這個二級緩存刪除valuesMap.remove(subKey, this);}}// the only path to reach here is with non-null value// 只有value的值不為空才能到達這里assert value != null;// wrap value with CacheValue (WeakReference)// 使用弱引用包裝生成的代理類CacheValue<V> cacheValue = new CacheValue<>(value);// put into reverseMap// 將cacheValue成功放入二級緩存后, 再對它進行標記reverseMap.put(cacheValue, Boolean.TRUE);// try replacing us with CacheValue (this should always succeed)// 用緩存包裝類替換this,必須成功,否則拋出異常if (!valuesMap.replace(subKey, this, cacheValue)) {throw new AssertionError("Should not reach here");}// successfully replaced us with new CacheValue -> return the value// wrapped by itreturn value;
}
最后一個核心方法 valueFactory.apply(key, parameter) 通過該方法就生成了代理類字節碼
Proxy.java->ProxyClassFactory->apply();
// 這個代理類工廠是在Proxy類初始化proxyClassCache靜態變量時傳入的
private static final class ProxyClassFactoryimplements BiFunction<ClassLoader, Class<?>[], Class<?>>
{// prefix for all proxy class names// 所有代理類的前綴,我們在debug的時候看到的JDK代理對象都是這樣的private static final String proxyClassNamePrefix = "$Proxy";// next number to use for generation of unique proxy class names// 用于生成代理類名字的計數器private static final AtomicLong nextUniqueNumber = new AtomicLong();@Overridepublic Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);// 驗證接口// 1. 驗證類加載器加載的對象接口是否是同一個// 2. 驗證類對象是否是一個接口// 3. 驗證此接口是否重復for (Class<?> intf : interfaces) {/** Verify that the class loader resolves the name of this* interface to the same Class object.*/Class<?> interfaceClass = null;try {interfaceClass = Class.forName(intf.getName(), false, loader);} catch (ClassNotFoundException e) {}if (interfaceClass != intf) {throw new IllegalArgumentException(intf + " is not visible from class loader");}/** Verify that the Class object actually represents an* interface.*/if (!interfaceClass.isInterface()) {throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");}/** Verify that this interface is not a duplicate.*/if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());}}// 生成的代理類的包名String proxyPkg = null; // package to define proxy class in// 代理類訪問控制符int accessFlags = Modifier.PUBLIC | Modifier.FINAL;/** Record the package of a non-public proxy interface so that the* proxy class will be defined in the same package. Verify that* all non-public proxy interfaces are in the same package.*/// 記錄非公共代理接口的包,以便在同一個包中定義代理類。驗證所有非公共代理接口都在同一個包中。for (Class<?> intf : interfaces) {int flags = intf.getModifiers();if (!Modifier.isPublic(flags)) {accessFlags = Modifier.FINAL;String name = intf.getName();int n = name.lastIndexOf('.');String pkg = ((n == -1) ? "" : name.substring(0, n + 1));if (proxyPkg == null) {proxyPkg = pkg;} else if (!pkg.equals(proxyPkg)) {throw new IllegalArgumentException("non-public interfaces from different packages");}}}if (proxyPkg == null) {// if no non-public proxy interfaces, use com.sun.proxy packageproxyPkg = ReflectUtil.PROXY_PACKAGE + ".";}/** Choose a name for the proxy class to generate.*/long num = nextUniqueNumber.getAndIncrement();// 代理類的全限定名稱:com.sun.proxy.$Proxy0String proxyName = proxyPkg + proxyClassNamePrefix + num;/** Generate the specified proxy class.*/// 核心代碼,生成代理類的字節碼byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);try {// 把代理類加載到JVM中,至此代理類創建完成了return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);} catch (ClassFormatError e) {/** A ClassFormatError here means that (barring bugs in the* proxy class generation code) there was some other* invalid aspect of the arguments supplied to the proxy* class creation (such as virtual machine limitations* exceeded).*/throw new IllegalArgumentException(e.toString());}}
}
我們再看看Factory這個內部工廠類,可以看到它的get方法是使用synchronized關鍵字進行了同步。進行get方法后首先會去驗證subKey對應的suppiler是否是工廠本身,如果不是就返回null,而WeakCache的get方法會繼續進行重試。如果確實是工廠本身,那么就會委托ProxyClassFactory生成代理類,ProxyClassFactory是在構造WeakCache的時候傳入的。所以這里解釋了為什么最后會調用到Proxy的ProxyClassFactory這個內部工廠來生成代理類。生成代理類后使用弱引用進行包裝并放入reverseMap中,最后會返回原裝的代理類
探究代理類長什么樣
上面把JDK動態代理的過程分析完了,但是我這探究的心里還是有一道過不去的坎,動態代理存在什么地方了?跟我們直接實現的類有什么區別呢?下面繼續研究解答這兩個問題
通過下面的main方法就可以輸出到磁盤代理對象
public class GenerateClient {public static void main(String[] args) {// 在main方法最前面增加該行代碼,這樣會輸出代理class文件System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");UserService userService = new UserService();UserInterface proxy = (UserInterface) new ProxyFactory(userService, null).getProxyObjectByTarget();proxy.update();}
}
通過上面的代碼就可以生成動態代理class文件了,在我們項目路徑下com/sun/proxy/$Proxy0.class,我的項目路徑是 D:/workspace-mine/spring_boot,那我都文件就在這個地址下 D:/workspace-mine/spring_boot/com/sun/proxy/$Proxy0.class
上面這種方式可以保存到磁盤上,但是在JVM中代理對象是保存在內存中的,我們看不到
代理對象的樣子
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.sun.proxy;import com.example.spring_boot.modules.study.proxyobject.jdkproxy.UserInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements UserInterface {private static Method m1;private static Method m4;private static Method m2;private static Method m0;private static Method m3;// 代理類的構造函數,其參數正是是InvocationHandler實例,// Proxy.newInstance方法就是通過通過這個構造函數來創建代理實例的public $Proxy0(InvocationHandler var1) throws {super(var1);}public final boolean equals(Object var1) throws {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final void save() throws {try {super.h.invoke(this, m4, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final String toString() throws {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final void update() throws {try {super.h.invoke(this, m3, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m4 = Class.forName("com.example.spring_boot.modules.study.proxyobject.jdkproxy.UserInterface").getMethod("save");m2 = Class.forName("java.lang.Object").getMethod("toString");m0 = Class.forName("java.lang.Object").getMethod("hashCode");m3 = Class.forName("com.example.spring_boot.modules.study.proxyobject.jdkproxy.UserInterface").getMethod("update");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}
可以看到上面重寫了toString、equals、hashCode三個方法,生成了5個方法變量,分別指向各自的方法,其中m4和m3是接口中的save和update方法
上面重要的一個是構造函數$Proxy0
,這個構造函數在代理對象還沒有生成前是不起做用的,直到代理對象生成了,這個構造器里面的參數就是我們在Proxy.newProxyInstance
中傳入的new InvocationHandler(){...}
這樣就開始執行我們構造器的方法了
如果想要在代理對象中執行代理方法可以直接這樣寫(main方法放在代理對象后面,需要把代理class轉成java)
public static void main(String[] args) {UserService userService = new UserService();$Proxy0 proxyObject = new $Proxy0(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("在代理對象中執行main方法開始...");method.invoke(userService, args);System.out.println("在代理對象中執行main方法結束...");return null;}});proxyObject.save();
}
Cglib動態代理
敬請期待...