代理是什么

代理模式,就是为其他的对象提供一种代理,以控制对这个对象的访问。Proxy代理对象与被代理对象对于调用方来说,完全一致,并且Proxy代理对调用方隐藏了被代理对象的实现细节。流程如下:

为什么要使用代理模式

没错,代理模式就是这么简单,可以这么理解,Proxy代理对象向调用方统一了对被代理对象的所有方法。有时,在调用被代理对象的正在执行的方法前,可能需要增加参数的校验逻辑,或者打印日志的逻辑;在执行完方法后,可能需要统计执行的时间,触发结束的事件等等逻辑。此时,如果在Proxy代理对象里动态地添加此类逻辑,就避免了在委托对象中硬编码。此时的执行流程1如下:

如果,此时,委托对象的执行逻辑是第三方服务提供的RPC服务或者HTTP服务, 其执行流程2如下:

Spring与Dubbo如何运用的代理模式

是不是以上两个执行流程很熟悉?是的,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, BeanClassLoaderAware, BeanFactoryAware {

/**

* 通过继承FactoryBean生成spring bean对象

*/

@Override

@Nullable

public Object getObject() throws BeansException {

initializeAdvisorChain();

if (isSingleton()) {

return getSingletonInstance();

}

else {

if (this.targetName == null) {

logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +

"Enable prototype proxies by setting the 'targetName' property.");

}

// 生成代理对象实例

return newPrototypeInstance();

}

}

/**

* 生成对象实例

*/

private synchronized Object newPrototypeInstance() {

ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());

TargetSource targetSource = freshTargetSource();

copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());

if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {

Class targetClass = targetSource.getTargetClass();

if (targetClass != null) {

copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));

}

}

copy.setFrozen(this.freezeProxy);

// 获取代理对象

return getProxy(copy.createAopProxy());

}

/**

* 通过AopProxy 生成代理对象

*/

protected Object getProxy(AopProxy aopProxy) {

return aopProxy.getProxy(this.proxyClassLoader);

}

}

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 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

if (chain.isEmpty()) {

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);

}

else {

// 结合拦截器chain生成的invocation

MethodInvocation invocation =

new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

// Proceed to the joinpoint through the interceptor chain.

retVal = invocation.proceed();

}

// Massage return value if necessary.

Class returnType = method.getReturnType();

if (retVal != null && retVal == target &&

returnType != Object.class && returnType.isInstance(proxy) &&

!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {

retVal = proxy;

}

else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {

throw new AopInvocationException(

"Null return value from advice does not match primitive return type for: " + method);

}

return retVal;

}

finally {

if (target != null && !targetSource.isStatic()) {

// Must have come from TargetSource.

targetSource.releaseTarget(target);

}

if (setProxyContext) {

// Restore old proxy.

AopContext.setCurrentProxy(oldProxy);

}

}

}

}

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();

}

}