Java 代理模式
1. 代理模式介绍
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。在后面我会解释这种间接性带来的好处。代理模式结构图(图片来自《大话设计模式》):
举个例子说明:比如现在某个明星有一个经纪人,其他人想要找这个明星的话就需要先找这个经纪人,再由经纪人去找这个明星,这里明星就是被代理类、经纪人就是代理类,其他人就是委托类当然经纪人在找明星之前可以先进行一些操作预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息。
java代理模式总体而言可以分为两种:
- 静待代理
- 动态代理
下面开始逐一介绍。
2. 静态代理
2.1 静态代理
静态代理:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。
针对前面的举例场景,下面用代码来实现。
2.2 静态代理实现
先分析一下整个实现过程:
这里有3个角色:
- 明星(被代理类)
- 明星经纪人(代理类)
- 追星族(委托类)
根据上面代理模式的类图,需要有一个Subject类,定义代理类和被代理的公用接口,这里就定位Person
类/接口;然后被代理类需要继承/实现这个Person
类,定为Celebrity
;代理类也需要继承/实现这个Person
类,并且需要有一个被代理类的引用,定为Agent
;至于这里的委托类就可以理解为我们的测试用例,用来触发向代理类发送请求。分析完成以后开始写代码。
首先创建Person
接口
/**
* 定义Person接口
*/
public interface Person {
//定义签名方法
public void signature();
}
创建Celebrity
类,实现Person
接口
/**
* 明星-被代理类
*/
public class Celebrity implements Person{
//实现签名方法
@Override
public void signature() {
System.out.println("签名:xxx");
}
}
创建Agent
类,实现Person
接口
/**
*经纪人-代理类
*/
public class Agent implements Person{
//定义被代理类的引用
private Celebrity celebrity;
public Agent(Celebrity celebrity){
this.celebrity = celebrity;
}
public Agent(){
this.celebrity = celebrity;
}
//实现签名方法
@Override
public void signature() {
celebrity.signature();
}
}
测试代码:
public class StaticProxyTest {
public static void main(String[] args) {
Celebrity celebrity = new Celebrity();
Agent agent = new Agent(celebrity);
agent.signature();
}
}
测试结果:
对于委托者而言,这里并没有直接通过明星(被代理类)来执行signature(签名)的动作,而是通过经纪人(Agent)来执行的。当然,这里在代理类进行请求的“转述”是并未执行其他的动作,下面加一下其他的动作。比如在转述签名之前需要“收费”,就很容易去实现了
/**
*经纪人-代理类
*/
public class Agent implements Person{
//定义被代理类的引用
private Celebrity celebrity;
public Agent(Celebrity celebrity){
this.celebrity = celebrity;
}
public Agent(){
this.celebrity = celebrity;
}
//实现签名方法
@Override
public void signature() {
//模拟收费动作
System.out.println("收费。。。");
celebrity.signature();
}
}
3 动态代理
1. 动态代理
动态代理的关键就在于动态两个子,和静态代理不同的是动态代理的代理类是在程序运行时才会被创建。在静态代理中,程序的代理类是已经人为手动的编写好,在程序运行之前就已经存在了。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类(针对于静态代理而言)中的方法。
2. 动态代理实现
在jdk中java.lang.reflect包下提供了一个Proxy
类和一个InvocationHandler
接口,这两个类/接口就是实现动态代理的关键,具体怎么使用来动态的生成代理类,后面具体讲。在静态类中包含了3个角色:
- 明星(被代理类)
- 明星经纪人(代理类)
- 追星族(委托类,这个其实不是很关键,说不说其实都无所谓)
并且明星(被代理类)、明星经纪人(代理类)都是我们自己自定义的,那现在要用动态代理去实现又该怎么做呢?还是先分析一下:首先明星(被代理类)肯定还是需要我们自己定义的,关键就在于明星经纪人(代理类)这个需要去动态的生成,要不然怎么叫做动态代理呢,那怎么去自动生成呢?在Proxy
类中提供一个方法:
/**
loader:传入类加载器
interfaces:Class类型的数组,里面就存放被代理类实现的接口,比如我们这里的Person.Class
InvocationHandler:自定义的InvocationHandler接口的实现类
*/
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//具体代码这里就先省略,读者要知道需要使用这个方法即可
}
分析基本完成之后,下面正式开始编码。
首先,还是需要一个Person
接口
/**
* 定义Person接口
*/
public interface Person {
//定义签名方法
public void signature();
}
然后是明星(被代理类)
/**
* 明星-被代理类
*/
public class Celebrity implements Person {
//实现签名方法
@Override
public void signature() {
System.out.println("签名:xxx");
}
}
下面就是关键部分了,需要定义一个InvocationHandler
接口的实现类,类中需要有一个被代理对象的实例。InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。
package dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
private T target;
public MyInvocationHandler(T target){
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//invoke方法
return method.invoke(target, args);
}
}
最后就是测试类了
package dynamicProxy;
import dynamicProxy.bean.Celebrity;
import dynamicProxy.bean.Person;
import java.lang.reflect.Proxy;
public class DynamicProxyTest {
public static void main(String[] args) {
//创建一个被代理对象
Person celebrity = new Celebrity();
//创建一个InvocationHandler,并且关联上被代理对象
MyInvocationHandler<Person> myInvocationHandler = new MyInvocationHandler<Person>(celebrity);
//生成代理对象,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person agent = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, myInvocationHandler);
agent.signature();
}
}
测试结果:
动态代理的好处就在于很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法,而是直接在InvocationHandler`接口的实现类中的invoke方法的前后进行处理就行了,比如添加日志、数据校验等等。
虽然前面已经用代码实现了动态代理,但是我相信还是有很多的读者对于动态代理还是一脸蒙蔽,生成的动态代理对象到底是怎么一回事?怎么生成的?这些都需要去研究它的源码才行
4 动态代理实现源码分析
前言:在读者开始阅读本部分内容之前,希望读者最好有“弱引用”的基础,没有这部分基础的读者可以先去大概了解一下再来阅读本部分内容会更轻松一些。
从开始创建动态代理对象开始分析
//生成代理对象,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person agent = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, myInvocationHandler);
先看下Proxy.newProxyInstance
的源码实现:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//判断InvocationHandler是否为空
Objects.requireNonNull(h);
//将接口类数组复制一份
final Class<?>[] intfs = interfaces.clone();
//执行权限检查
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//查找或者是生成一个特定的代理类对象,就是在这里生成了代理类具体实现在后面介绍
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
//从代理类中查找参数为InvocationHandler的构造器
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 检测构造器是否是Public修饰,如果不是则强行转换为可以访问的。
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);
}
}
整个过程就分析完了,可以看到最为核心的一步就是getProxyClass0(loader, intfs)
,利用这个方法来得到代理类对应的Class对象,后面再利用反射的只是来实例,所以下面就需要针对分析getProxyClass0(loader, intfs)
方法进行解析,实现如下:
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
//接口类对象数组不能大于65535个,否则抛出异常
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 从代理类对象缓存中,根据类加载器和接口类对象数组查找代理类对象
return proxyClassCache.get(loader, interfaces);
}
可以看到getProxyClass0(loader, intfs)
方法的结果是从proxyClassCache
缓存中获取的,看一下这个缓存
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
这里调用了WeakCache
的构造方法,为WeakCache
里面的2个变量赋值:
//subKeyFactory赋值KeyFactory对象
private final BiFunction<K, P, ?> subKeyFactory;
//valueFactory赋值ProxyClassFactory
private final BiFunction<K, P, V> valueFactory;
至于subKeyFactory、valueFactory再这里发挥什么作用,往下看,后面用到的时候会进行说明。
现在看下 proxyClassCache.get(loader, interfaces)
的get方法实现,也就是WeakCache
的get
方法实现:
public V get(K key, P parameter) {
//判断传入参数parameter是否为空
Objects.requireNonNull(parameter);
//删除过时的条目,这个具体实现后面说
expungeStaleEntries();
//生成缓存key对象实例,如果key = null,cacheKey = new Object();
Object cacheKey = CacheKey.valueOf(key, refQueue);
//从map中根据cacheKey读者缓存数据
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
//判断读取到的缓存数据是否为null
if (valuesMap == null) {
//如果为null,就新增
//putIfAbsent方法解释:如果值存在则返回值,并且不对原来的值做任何更改,如果不存在则新增,并返回null,针对这里的情况就属于后者,所以oldValuesMap就是null,并且这时候map中会新增一个key-->value为Cachekey-->new ConcurrentHashMap<>()的键值对,而valuesMap = new ConcurrentHashMap<>()
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());
//这个判断中的代码不会执行
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
//获取sbukey,这里subKeyFactory就是调用WeakCache构造方法时所赋值的KeyFactory对象,所以这里实际上是调用KeyFactory的apply方法,至于实现方法后面说
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//根据subKey去从valuesMap中获取Supplier变量,这时候肯定获取不到,因为valuesMap = new ConcurrentHashMap<>(),里面没东西
Supplier<V> supplier = valuesMap.get(subKey);
//定义Factory变量,注意Factory实现了Supplier接口
Factory factory = null;
//这里定义了一个“永真”循环,只要没有执行return 语句,就会一直执行
while (true) {
if (supplier != null) {
//4. 从工厂中获取代理类对象
V value = supplier.get();
if (value != null) {
//5. 返回代理对象
return value;
}
}
if (factory == null) {
//1. 实例化Factory工厂
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
//2. 给valuesMap中赋值
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// 3. factory赋值给supplier变量
supplier = factory;
}
} else {
//下面的就不看了,不会执行
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
} else {
supplier = valuesMap.get(subKey);
}
}
}
}
关于WeakCache
的get
方法就大体上说完了,但是里面有一些细节以及调用的重要方法还需要进行说明。
因为程序中Proxy.newProxyInstance是第一次执行,所以while循环开始的时候,supplier,valuesMap都是null。在这个前提下,我为代码的执行顺序做了一个编号,从1-5执行。
可以看到动态代理的代理对象就是再第5步返回的,在第4步产生的,而第4步中的supplier变量其实就是在第3步中赋值,所以其实动态代理的代理对象是通过Factory.get方法产生的,下面就分析一下这个方法。Factory
是WeakCache
的内部类,看实现
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中subKey对应的是否是Factory变量,不是的话直接return null
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
return null;
}
//定义value变量,也就是动态代理变量
V value = null;
try {
//调用valueFactory的apply方法,这里valueFactory实际上是ProxyClassFactory,有疑问的就看下WeakCache的构造方法,所以实际上是调用ProxyClassFactory.apply方法
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;
//使用CacheValue封装
CacheValue<V> cacheValue = new CacheValue<>(value);
//放进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");
}
//返回动态代理对象
return value;
}
}
Factory.get方法中通过执行value = Objects.requireNonNull(valueFactory.apply(key, parameter))
获取了value,也就是动态代理对象,而这个这里valueFactory
实际上是ProxyClassFactory
,所以实际上调用的是ProxyClassFactory.apply
方法,下面针对ProxyClassFactory
进行分析。
ProxyClassFactory
也是WeakCache
的内部类,代码如下:
//一个利用给定的类加载器和接口类数组生成,定义并返回代理类对象的工厂方法
private static final class ProxyClassFactory implements
BiFunction<ClassLoader, Class<?>[], Class<?>>{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
//apply方法实现
@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) {
}
//判定interfaceClass和intf是否相等
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
//判定interfaceClass是否是接口,不是接口就直接抛出异常
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
//向interfaceSet这个IdentityHashMap中插入元素,如果插入的是已经存在的元素,就会返回原来的value值;如果是新增元素,会返回null.
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
//代理类的包名
String proxyPkg = null;
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) {
//ReflectUtil.PROXY_PACKAGE的值是:com.sun.proxy.
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
//自增,从0开始,每次执行都会+1
long num = nextUniqueNumber.getAndIncrement();
//拼接完成的代理对象全类名,也就是com.sun.proxy.$Proxy0
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//生成代理类class文件
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// 返回代理类对象
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());
}
}
}
通过ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags)
成了了代理对象的class文件,那么现在怎么看这个代理对象里面的内容呢?只需要一行代码:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
这里我顺便把完整的的动态代理测试demo发一下,怕有人不知道这句代码在哪里添加:
public class DynamicProxyTest {
public static void main(String[] args) {
//创建一个被代理对象
Person celebrity = new Celebrity();
//创建一个InvocationHandler,并且关联上被代理对象
MyInvocationHandler<Person> myInvocationHandler = new MyInvocationHandler<Person>(celebrity);
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
//生成代理对象,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person agent = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, myInvocationHandler);
agent.signature();
}
}
下面看一下生成的代理对象里面的代码:
package com.sun.proxy;
import dynamicProxy.bean.Person;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
//实现了Proxy类继承了Person接口
public final class $Proxy0 extends Proxy implements Person {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
//构造方法,直接调用父类的构造方法,也就是Proxy类中的构造方法,传入参数就是我前面测试demo里面的MyInvocationHandler对象myInvocationHandler
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
//重写equals方法
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 signature() throws {
try {
//调用父类中InvocationHandler的invoke方法,其实就是调用MyInvocationHandler对象myInvocationHandler的invoke方法,传入m3,具体m3代表什么方法,下面说
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
//重写toString方法
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);
}
}
//重写hashCode方法
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);
}
}
//静态代码块,在调用动态代理对象中的方法之前,会先执行这里面的代码
static {
try {
//m1对应equals方法
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
//m3对应signature方法
m3 = Class.forName("dynamicProxy.bean.Person").getMethod("signature");
//m2对应toString方法
m2 = Class.forName("java.lang.Object").getMethod("toString");
//mo对应hashCode方法
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
到这里的话,动态代理对象就分析完成了。接着前面的继续说,其实到现在为止都只是对
Class<?> cl = getProxyClass0(loader, intfs);
这行代码进行分析,下面接着往下看,先把整个源码贴出来,方便观看
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//判断InvocationHandler是否为空
Objects.requireNonNull(h);
//将接口类数组复制一份
final Class<?>[] intfs = interfaces.clone();
//执行权限检查
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//查找或者是生成一个特定的代理类对象,就是在这里生成了代理类具体实现在后面介绍
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
//从代理类中查找参数为InvocationHandler的构造器
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 检测构造器是否是Public修饰,如果不是则强行转换为可以访问的。
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//利用构造器实例化代理类对象,这里的h参数就是我测试demo中定义的`MyInvocationHandler类型的变量myInvocationHandler
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);
}
}
看下return cons.newInstance(new Object[]{h})
这句,这里就利用了反射的方式来调用c1(也就是动态代理对象)中的构造函数,也就是:
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
通过整个构造函数,实现了对动态代理对象父类Proxy
的构造函数的调用,进而为Proxy
类中的InvocationHandler
类型的变量h赋值,赋值内容就是我测试demo里面的MyInvocationHandler
类型的变量myInvocationHandler
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
//h变量定义
protected InvocationHandler h;
最后由动态代理对象中的signature
方法调用到代理类中的signature
也就顺理成章了,其实sprng的AOP(面向切面编程)就是基于动态代理实现的。
关于整个动态代理的源码实现就分析完了,最后在捋一下需要注意的地方:
- 一定要有一个接口(interface)。被代理类一定要实现一个接口,比如本文中的被代理类就实现了
Person
接口:
public class Celebrity implements Person {
//实现签名方法
@Override
public void signature() {
System.out.println("签名:xxx");
}
}
说的更直白一点就是动态代理只能接口(Interface)进行代理,Java的继承机制注定了这些动态代理类们无法实现对class的动态代理。