一、首先要講動態代理,先要從代理模式講起
// 定義公共接口
public interface IShop {
public void buy();
}
public class MyBuy implements IShop {
@Override
public void buy() {
System.out.print("真正的買東西");
}
}
public class Static implements IShop {
private IShop innerShop;
public Static(IShop innerShop) {
this.innerShop = innerShop;
}
@Override
public void buy() {
innerShop.buy();
}
}
Static s = new Static(new MyBuy());
s.buy();
上面就是代理模式的簡單例子,代理模式的作用有兩個,一個是爲保護真正的是代碼實現類,不讓它直接暴露給客戶,起一箇中介的作用。另一個是可以在代理的過程,給代碼的業務實現加點料,後者一般被拿來做程序員該做的事。
二、動態代理
上面這個代理,需要編譯之前將代理類寫好,打包成.class。而動態代理是在運行時,再生成相應的.class。
先來看動態代理的代碼實現
public class Dynamic implements InvocationHandler {
private Object object;
public Dynamic(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(object, args);
}
}
IShop shop = new MyBuy();
Dynamic dynamic = new Dynamic(shop);
IShop proxy = (IShop) Proxy.newProxyInstance(shop.getClass().getClassLoader(), new Class[]{IShop.class}, dynamic);
proxy.buy();
核心的代碼就是 Proxy.newProxyInstance()生成一個代理類,並返回它的對象
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
// 生成代理類的.class並獲得對應的Class
Class<?> cl = getProxyClass0(loader, intfs);
try {
// 獲得構造方法,並且這個構造方法有個參數爲InvocationHandler
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//
if (!Modifier.isPublic(cl.getModifiers())) {
cons.setAccessible(true);
}
// 獲得代理類的實例 等同於 Static s = new Static(new MyBuy());
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
getProxyClass0()這個方法在運行時生成一個名爲 公共接口的包名+前綴:“$Proxy"+累計的唯一編碼的數字
class “$Proxy"+累計的唯一編碼的數字 implements IShop{
InvocationHandler h;
public “$Proxy"+累計的唯一編碼的數字(InvocationHandler h){
this.h = h;
...
}
@Override
public void buy() {
...
this.h.invoke(..);
}
}
當調用相應接口的方法時,就是調用到invoke方法
相關的源代碼:
class Proxy{
...
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// 所有代理類名稱的前綴
private static final String proxyClassNamePrefix = "$Proxy";
// 下一個用於生成唯一代理類名稱的數字
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
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;
// 獲得包名
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 the default package.
proxyPkg = "";
}
{
// Android-changed: Generate the proxy directly instead of calling
// through to ProxyGenerator.
List<Method> methods = getMethods(interfaces);
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
validateReturnTypes(methods);
List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
// 獲得接口的方法結合
Method[] methodsArray = methods.toArray(new Method[methods.size()]);
// 獲得接口方法拋出異常集合
Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
// 拼成代理類的名字
String proxyName = proxyPkg + proxyClassNamePrefix + num;
return generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
}
}
...
}
具體生成.class的代碼實現在native中實現,generateProxy是一個native方法,返回值爲Class。在這個方法中做的事情,大概就是拼一個.class的二進制的文本,並加載進來。
以上就是動態代理的全部核心源代碼實現(Java層),接下來解析其中一個重要的數據結構WeakCache
三、Weakcache
這個數據結構作用:當需要get(..)某個值時,首先在緩存中找,如果緩存中沒有該值,便生成一個值,返回並放入緩存中。在緩存中使用弱引用的方式存儲該值。
這個類的變量
final class WeakCache<K, P, V> {
private final ReferenceQueue<K> refQueue
= new ReferenceQueue<>(); // classLeader弱引用對應ReferenceQueue,用於更新map,刪除以回收的key
// the key type is Object for supporting null key
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
= new ConcurrentHashMap<>(); // 主存儲map,key值爲外部傳入classleader的弱引用,
value爲以外部傳入公共接口生成CacheKey和對應生成代理cLass<?>構成Map集合
private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
= new ConcurrentHashMap<>(); // 用於存儲代理Class<?>的弱引用的map,起標誌作用
private final BiFunction<K, P, ?> subKeyFactory; // 通過外部傳入的公共接口生成key值的工廠,
這個key用於上面map的value,即對應的ConcurrentMap
private final BiFunction<K, P, V> valueFactory; // 連接native生成代理CLass<?>的工廠
}
Weakcache.get(..)方法
class EakCache{
...
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
// 通過refQueue清理掉已經回收的Classleader
expungeStaleEntries();
// 通過對應的Classleader生成CacheKey,作爲map的key,注意:CacheKey重寫hash
Object cacheKey = CacheKey.valueOf(key, refQueue);
// 從緩存中獲得對應的value,如果不存在,新建一個
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// 通過外部的接口,生成對應的suKey
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
// 從緩存中找是否有緩存好的代理Class<?>,即CacheValue對象
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// 可能是Factory或CacheValue <V>實例
V value = supplier.get();
if (value != null) {
return value;
}
}
// 配置一個ProxyClassFactory,用於生成一個新的代理CLass<?>
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
// 將對應的Factory放入,但在Factory的get方法中會調換
成代理Class<?>的CacheValue對象(後面說明)
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
supplier = factory;
}
} else {
// 更新
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
} else {
// 如果替換失敗,換回之前的
supplier = valuesMap.get(subKey);
}
}
}
}
...
}
上面提到的Factory源代碼:
private final class Factory implements Supplier<V> {
private final K key;
private final P parameter; // 外部傳入接口
private final Object subKey; // 外部傳入接口生成的key
private final ConcurrentMap<Object, Supplier<V>> valuesMap; // map對應的value
Factory(K key, P parameter, Object subKey,
ConcurrentMap<Object, Supplier<V>> valuesMap) {
this.key = key;
this.parameter = parameter;
this.subKey = subKey;
this.valuesMap = valuesMap;
}
@Override
public synchronized V get() { // serialize access
// 如果緩存裏有,直接使用
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
return null;
}
// 調用native生成新的代理Class<?>
V value = null;
try {
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
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue<V> cacheValue = new CacheValue<>(value);
// 將生成代理Class<?>CacheValue替換原來存進去的Factory
if (valuesMap.replace(subKey, this, cacheValue)) {
// 同時也存入reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}