定义和类型
![](https://img.haomeiwen.com/i4685968/24449b2f47dd799e.png)
使用场景
![](https://img.haomeiwen.com/i4685968/df2273a8cd6adeef.png)
优点
![](https://img.haomeiwen.com/i4685968/fa30c7d396320dbb.png)
缺点
![](https://img.haomeiwen.com/i4685968/e1ebfd39bec5d413.png)
扩展
![](https://img.haomeiwen.com/i4685968/45847270ecd20905.png)
Spring 代理
![](https://img.haomeiwen.com/i4685968/a3085a40c6fc1706.png)
代理速度对比
![](https://img.haomeiwen.com/i4685968/2258438ca278ce74.png)
相关设计模式
![](https://img.haomeiwen.com/i4685968/88870dba87223cb4.png)
2 实战
2.1 静态代理
![](https://img.haomeiwen.com/i4685968/5fd5fb5774910f8f.png)
![](https://img.haomeiwen.com/i4685968/5e4a36e67a815915.png)
![](https://img.haomeiwen.com/i4685968/1283a4df2190817d.png)
![](https://img.haomeiwen.com/i4685968/4eb7d64aa35537ed.png)
看 UML 图
展开包节点
![](https://img.haomeiwen.com/i4685968/c9b76345047b66e2.png)
![](https://img.haomeiwen.com/i4685968/ca0c55bce5e56a59.png)
动态代理
![](https://img.haomeiwen.com/i4685968/e7884e6a6405d741.png)
![](https://img.haomeiwen.com/i4685968/a24f325c92056e42.png)
![](https://img.haomeiwen.com/i4685968/6d7cb5dbb70be0fb.png)
源码分析
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
*
* <p>{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
* {@code Proxy.getProxyClass} does.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
* @throws SecurityException if a security manager, <em>s</em>, is present
* and any of the following conditions is met:
* <ul>
* <li> the given {@code loader} is {@code null} and
* the caller's class loader is not {@code null} and the
* invocation of {@link SecurityManager#checkPermission
* s.checkPermission} with
* {@code RuntimePermission("getClassLoader")} permission
* denies access;</li>
* <li> for each proxy interface, {@code intf},
* the caller's class loader is not the same as or an
* ancestor of the class loader for {@code intf} and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to {@code intf};</li>
* <li> any of the given proxy interfaces is non-public and the
* caller class is not in the same {@linkplain Package runtime package}
* as the non-public interface and the invocation of
* {@link SecurityManager#checkPermission s.checkPermission} with
* {@code ReflectPermission("newProxyInPackage.{package name}")}
* permission denies access.</li>
* </ul>
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
* {@code null}
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException {
// 检查代理对象非空
Objects.requireNonNull(h);
// 安全检查
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
![](https://img.haomeiwen.com/i4685968/f0e2b9ad2a063d3f.png)
生成代理类实现方法
- 检查接口数量
- 代理缓存
/**
* 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) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
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) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
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 = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
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);
}
}
网友评论