代理(Proxy)是什么?为什么要使用代理模式?Spring与Dubbo如何运用代理模式的?

代理是什么

代理模式,就是为其他的对象提供一种代理,以控制对这个对象的访问。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<Void>() {
                    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<Object>, 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<Object> 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> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        // 使用Proxy 类生成指定接口interfaces的代理类
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
    }

    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        return new AbstractProxyInvoker<T>(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();
    }
}

猜你喜欢

转载自blog.csdn.net/new_com/article/details/106558077
今日推荐