代理模式,就是为其他的对象提供一种代理,以控制对这个对象的访问。Proxy代理对象与被代理对象对于调用方来说,完全一致,并且Proxy代理对调用方隐藏了被代理对象的实现细节。流程如下:
没错,代理模式就是这么简单,可以这么理解,Proxy代理对象向调用方统一了对被代理对象的所有方法。有时,在调用被代理对象的正在执行的方法前,可能需要增加参数的校验逻辑,或者打印日志的逻辑;在执行完方法后,可能需要统计执行的时间,触发结束的事件等等逻辑。此时,如果在Proxy代理对象里动态地添加此类逻辑,就避免了在委托对象中硬编码。此时的执行流程1如下:
如果,此时,委托对象的执行逻辑是第三方服务提供的RPC服务或者HTTP服务, 其执行流程2如下:
是不是以上两个执行流程很熟悉?是的,Spring中AOP的实现就类似于流程1,在Spring中使用JDK和Cglib两种动态代理方式来实现了对被代理对象的切面逻辑的动态扩展。Dubbo远程服务调用类似于流程2,被代理对象的实际实现逻辑在远程的服务提供方,客户端与服务端通过TCP协议进行传输,在Dubbo中远程服务的调用通过JDK和Javassist两种动态代理方式进行动态代理。以下就以JDK动态代理方式来介绍AOP的实现,以及Dubbo远程服务的调用。
JDK的动态代理的原理可以参考Java JDK 动态代理(AOP)使用及实现原理分析。简单理解,就是JDK的动态代理通过Proxy对象和InvocationHandler接口来实现。Proxy类用于动态生成指定接口(interface)实现类的字节码。然后,加载为对应的Class类,利用反射机制生成代理类的实例对象;通过InvocationHandler扩展被代理对象的业务逻辑,InvocationHandler定义方法调用逻辑处理,其接口定义如下:
public interface InvocationHandler {
/**
* 方法调用处理 proxy为代理的对象,method为方法反射类,args为调用方法的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
Proxy类部分的源码如下:
/**
* 生成代理对象
*/
// Proxy.class
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);
}
/*
* 生成代理的对象的Class对象
*/
Class> cl = getProxyClass0(loader, intfs);
/*
* 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() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 根据InvocationHandler生成代理对象
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);
}
}
Spring中AOP的实现
在Spring中基于AspectJ与JDK动态代理共同实现了Spring的AOP。AspectJ用于指定需要被横切的具体位置,以及具体逻辑。使用JDK动态代理技术把AspectJ增强的逻辑整合到给定接口的动态代理生成的实现类,以实现了切面逻辑的整合。在Spring中,动态生成代理对象的逻辑,主要依靠ProxyFactoryBean类与JdkDynamicAopProxy类实现。ProxyFactoryBean实现了FactoryBean接口,用于获取Spring的bean对象,生成代理对象的逻辑在其getObject方法实现,ProxyFactoryBean的部分源码如下:
/**
* 在spring中生成AOP代理的bean对象
*/
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean
JdkDynamicAopProxy实现了AopProxy接口,用于生成代理对象。也实现了InvocationHandler接口,定义了对代理对象业务的扩展,其源码如下:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
/**
* 获取代理对象
*/
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 调用Proxy的静态方法newProxyInstance 生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
/**
* 扩展被代理访问的业务逻辑
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
// 获取拦截器
List
Dubbo基于JDK动态代理的服务调用
在Dubbo远程服务的调用过程中,默认情况下,使用Netty与服务提供方进行通信,定义DubboInvoker使用服务通信的客户端发起远程调用。在使用JDK动态代理时,在JdkProxyFactory中实现ProxyFactory接口,使用JDK的Proxy代理类,生成代理对象DubboInvoker,其的源码如下:
public class JdkProxyFactory extends AbstractProxyFactory {
@Override
@SuppressWarnings("unchecked")
public T getProxy(Invoker invoker, Class>[] interfaces) {
// 使用Proxy 类生成指定接口interfaces的代理类
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
}
@Override
public Invoker getInvoker(T proxy, Class type, URL url) {
return new AbstractProxyInvoker(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class>[] parameterTypes,
Object[] arguments) throws Throwable {
Method method = proxy.getClass().getMethod(methodName, parameterTypes);
// 生成远程调用的Invoker
return method.invoke(proxy, arguments);
}
};
}
}
使用InvokerInvocationHandler定义远程服务调用参数RpcInvocation的封装,已经具体方法的执行逻辑,其源码如下:
public class InvokerInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
String methodName = method.getName();
Class>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) {
if ("toString".equals(methodName)) {
return invoker.toString();
} else if ("$destroy".equals(methodName)) {
invoker.destroy();
return null;
} else if ("hashCode".equals(methodName)) {
return invoker.hashCode();
}
} else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
return invoker.equals(args[0]);
}
// 封装远程调用参数RpcInvocation
RpcInvocation rpcInvocation = new RpcInvocation(method, invoker.getInterface().getName(), args);
String serviceKey = invoker.getUrl().getServiceKey();
rpcInvocation.setTargetServiceUniqueName(serviceKey);
if (consumerModel != null) {
rpcInvocation.put(Constants.CONSUMER_MODEL, consumerModel);
rpcInvocation.put(Constants.METHOD_MODEL, consumerModel.getMethodModel(method));
}
// 执行被代理的业务方法
return invoker.invoke(rpcInvocation).recreate();
}
}