Java的三種代理模式&完整源碼分析


Java的三種代理模式&完整源碼分析

參考資料:

博客園-Java的三種代理模式

簡書-JDK動態代理-超詳細源碼分析

[博客園-WeakCache緩存的實現機制](https://www.cnblogs.com/liuyun1995/p/8144676.html)

靜態代理

靜態代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現相同的接口或者是繼承相同父類

  1. 可以做到在不修改目標對象的功能前提下,對目標功能擴展
  2. 缺點:
    1. 因為代理對象需要與目標對象實現一樣的接口,所以會有很多代理類,類太多
    2. 同時,一旦接口增加方法,目標對象與代理對象都要維護

如何解決靜態代理中的缺點呢?答案是可以使用動態代理方式

實現靜態代理的步驟

  1. 定義業務接口
  2. 被代理類實現業務接口
  3. 定義代理類並實現業務接口
  4. 最后便可通過客戶端進行調用(這里可以理解成程序的main方法里的內容)

定義接口 UserInterface

public interface UserInterface {
    // 保存用戶信息
    void save();
}

定義接口的實現類 UserService

public class UserService implements UserInterface  {
    @Override
    public void save() {
        System.out.println("[靜態代理] 保存用戶信息");
    }
}

定義靜態代理 UserProxy

public class UserProxy implements UserInterface  {

    private UserInterface userInterface;

    public UserProxy(UserInterface userInterface) {
        this.userInterface = userInterface;
    }

    /**
     * save 代理方法
     */
    @Override
    public 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動態代理的優勢是實現無侵入式的代碼擴展,也就是方法的增強;讓你可以在不用修改源碼的情況下,增強一些方法;在方法的前后你可以做你任何想做的事情(甚至不去執行這個方法就可以)

特點

  1. 在程序運行時,通過反射機制動態生成
  2. 動態代理類通常代理接口下的所有類
  3. 動態代理事先不知道要代理的是什么,只有在運行的時候才能確定
JDK動態代理
  1. 動態代理的調用處理程序必須事先InvocationHandler接口,及使用Proxy類中的newProxyInstance方法動態的創建代理類
  2. Java動態代理只能代理接口,要代理類需要使用第三方的CLIGB等類庫

問題

  1. 為什么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動態代理的步驟

  1. 創建被代理的接口和類
  2. 創建InvocationHandler接口的實現類,在invoke方法中實現代理邏輯
  3. 通過Proxy的靜態方法newProxyInstance( ClassLoaderloader, Class[] interfaces, InvocationHandler h)創建一個代理對象
  4. 使用代理對象

定義接口 UserInterface

public interface UserInterface {
    // 保存用戶信息
    void save();

    // 更新用戶信息
    void update();
}

定義接口的實現類 UserService

public class UserService implements UserInterface {
    @Override
    public void save() {
        System.out.println("[JDK動態代理]  保存用戶信息");
    }

    @Override
    public 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類型是為了存儲null
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();
    
    // reverseMap記錄了所有代理類生成器是否可用, 這是為了實現緩存的過期機制
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap<>();
    
    // 生成二級緩存key的工廠, 這里傳入的是KeyFactory
    private final BiFunction<K, P, ?> subKeyFactory;
    
    // 生成二級緩存value的工廠, 這里傳入的是ProxyClassFactory
    private 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, 作為一級緩存的key
	Object 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,沒有放入會返回當前的value
		ConcurrentMap<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, keyx
	Object 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 Factory
		if (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 value
	V 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 it
	return value;
}

最后一個核心方法 valueFactory.apply(key, parameter) 通過該方法就生成了代理類字節碼
Proxy.java->ProxyClassFactory->apply();

// 這個代理類工廠是在Proxy類初始化proxyClassCache靜態變量時傳入的
private static final class ProxyClassFactory
        implements 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();

	@Override
	public 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 package
			proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
		}

		/*
		 * Choose a name for the proxy class to generate.
		 */
		long num = nextUniqueNumber.getAndIncrement();
		
		// 代理類的全限定名稱:com.sun.proxy.$Proxy0
		String 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() {
		@Override
		public 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動態代理

敬請期待...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM