引言
Java动态代理是代理模式的一种,代理模式就是:为另一个对象提供一个替身或占位符一控制对这个对象的访问。举个例子,明星都有一个经济人,一般各种商业活动,都会先找到经济人进行洽谈,洽谈成功,才会给明星安排上活动,经纪人就是明星的代理。
在java.lang.reflect包中实现了对代理的支持,利用这个包,可以在运行时动态的创建一个代理类。通过实现一个或多个接口,并将方法的调用转发到你所指定的类。
看下java动态代理的类图:

Proxy类是java根据Subject动态创建的,我们干预不了这个类,所以我们不能在这个类中,去做什么。我们需要一个方式来告诉Proxy我们要做什么。所以我们需要一个InvocationHandler来响应Proxy类的方法调用。可以理解为Proxy收到方法调用后,会将通过InvocationHandler来做实际的工作(其实InvocationHandler也是委托RealSubject来做的)。
简单demo代码
/**
* 接口
*/
public interface Subject {
void doSomething();
}
/**
* 接口实现类
*/
public class RealSubject implements Subject{
public void doSomething(){
System.out.println( "I'm doSomething()" );
}
}
/**
* 实现Invocation,重写invoke方法
* 在此方法中,实现对要请求的真正的方法进行一些控制:比如方法前后执行一些操作
*/
public class ProxyHandler implements InvocationHandler {
private Object proxied;
public ProxyHandler(Object proxied) {
this.proxied = proxied;
}
// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数是代理类实例,第二个参数是被调用的方法对象
// 第三个方法是调用参数。InvocationHandler根据这三个参数进行预处理或分派到委托类实例上执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在调用具体目标对象之前,可以执行一些功能处理
System.out.println("before doSomething");
//转调具体目标对象的方法
Object obj = method.invoke(proxied, args);
//在调用具体目标对象之后,可以执行一些功能处理
System.out.println("after doSomething");
return obj;
}
}
/**
* 创建动态代理,并调用其方法
*/
public class DynamicProxy {
public static void main(String[] args) {
RealSubject real = new RealSubject();
/**
* Proxy.newProxyInstance就是创建动态代理类的方法,此方法接收三个参数:
* 1、和要代理的类RealSubject实现的接口相同的类加载器
* 2、一组接口
* 3、InvocationHandler实例
* 方法返回的是一个Object对象,因为生成的代理类实现了Subject接口,所以可以强转为Subject
*/
Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new ProxyHandler(real));
//代理类对象调用doSomething()方法,会调用InvocationHandler实例中的invoke方法来做真正的工作
proxySubject.doSomething();
}
}

源码分析
从Proxy类的静态方法newProxyInstance开始,动态代理实例就是通过此方法生成的。此方法接收三个参数:1、类加载器;2、代理需要实现的一组接口;3、InvocationHandler类型的实例。在进一步分析newProxyInstance方法之前,我们先概览一下Proxy这个类:
1、Proxy类静态属性和静态方法清单:
/**-------------静态方法----------------*/
//代理类的构造器参数类型 */
private static final Class<?>[] constructorParams = { InvocationHandler.class };
// 用于维护类装载器对象到其对应的代理类缓存
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
//调用处理器的实例.
protected InvocationHandler h;
/**-------------静态方法----------------*/
// 方法 1:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
// 方法2:内部私有静态方法。该方法用于为指定类装载器、一组接口生成动态代理类对象
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces)
进入到newProxyInstance方法内,去看方法的执行过程(如下图),我们看到getProxyClass0方法,这个方法返回代理类对象,这个方法接收两个参数:类加载器和代理的一组接口。

接下来,我们看getProxyClass0方法内部

到这里,我们看到关键代码就是,从proxyClassCache这个静态属性中获取类对象。这个静态属性,上面我们橄榄过了,就是一个维护类加载器到其代理类实例的缓存。接下来我们看proxyClassCache.get方法,看这个方法之前,我们先分析下这个静态属性:
看完了这些相关的我们就接着看proxyClassCache.get方法,这个方法接收两个参数,一个是类加载器,一个接口。
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
//确保key不为空
Object cacheKey = CacheKey.valueOf(key, refQueue);
/**延迟装载第二个valuesMap
* 如果根据cache获取不到valuesMap,则创建一个
* ConcurrentHashMap加到map中
*
*/
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;
}
}
/** 获取第二map即valuesMap的key,
*这个subKeyFactory就是我们前面看过的KeyFactory,这个factroy用来产生一个key
*然后根据这个key去获取我们需要的值,
* 这个值就是我们需要的动态代理类对象
*其实第一次获取的时候,缓存中是空的,这个时候,会通过Factory这个WeakCache类中的私有类来生成这个动态代理类对象
*/
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);
}
}
}
}
// 生成动态代理类对象的私有内部类
private final class Factory implements Supplier<V> { private final K key; private final P parameter; private final Object subKey; private final ConcurrentMap<Object, Supplier<V>> valuesMap; 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 // 再次检查valuesMap时候包含需要查找的动态代理类对象 Supplier<V> supplier = valuesMap.get(subKey); if (supplier != this) { return null; } // 如果supplier == this 说明还没生成动态代理类对象,就新生成一个
V value = null;
try {
/* 如果supplier == this 说明还没生成动态代理类对象,就新生成一个 * 找到生成字节码的地方了,就是valueFactory.apply这个方法。前面我们看到过proxyClassCache这个Proxy类中的静态属性,这个属性在初始化的时候传了 * ProxyClassFactory这个类实例到WeakCache的构造方法中,就是赋值给valueFactory,现在调用其apply方法来动态生成代理类的字节码了 * 生成的字节码就会保存到valuesMap中了
*/ 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); // put into reverseMap reverseMap.put(cacheValue, Boolean.TRUE); // try replacing us with CacheValue (this should always succeed) 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; } }
字节码生成的过程已经搞清楚了,回到Proxy类的newProxyInstance方法,前面我们进行到此方法中的getProxyClass0中去分析了,如下图所示:
现在我们接着往下看

/** * 接口 */public interface Subject { void doSomething();}