zoukankan      html  css  js  c++  java
  • Spring AOP分析(2) -- JdkDynamicAopProxy实现AOP

    上文介绍了代理类是由默认AOP代理工厂DefaultAopProxyFactory中createAopProxy方法产生的。如果代理对象是接口类型,则生成JdkDynamicAopProxy代理;否则生成ObjenesisCglibAopProxy代理,ObjenesisCglibAopProxy代理是继承于CglibAopProxy。下面先从熟悉的入手,选择JdkDynamicAopProxy分析。

    构造器

    查看源码,可以看到JdkDynamicAopProxy是一个final类,不能被继承和实现。其实现了AopProxy, InvocationHandler, Serializable接口,如下所示:

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
    

    下面看看JdkDynamicAopProxy 构造器,源码如下:

    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
      Assert.notNull(config, "AdvisedSupport must not be null");
      if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
        throw new AopConfigException("No advisors and no TargetSource specified");
      }
      this.advised = config;
    }
    

    从构造器可以看出,JdkDynamicAopProxy依赖于AdvisedSupport,根据config配置信息创建动态代理对象。代码中config.getAdvisors()提供的是Advisor列表。

    getProxy

    getProxy 方法是实现AopProxy接口,源码如下:

    	@Override
    	public Object getProxy() {
    		return getProxy(ClassUtils.getDefaultClassLoader());
    	}
    
    	@Override
    	public Object getProxy(ClassLoader classLoader) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    		}
    		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    	}
    
    	/**
    	 * Finds any {@link #equals} or {@link #hashCode} method that may be defined
    	 * on the supplied set of interfaces.
    	 * @param proxiedInterfaces the interfaces to introspect
    	 */
    	private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
    		for (Class<?> proxiedInterface : proxiedInterfaces) {
    			Method[] methods = proxiedInterface.getDeclaredMethods();
    			for (Method method : methods) {
    				if (AopUtils.isEqualsMethod(method)) {
    					this.equalsDefined = true;
    				}
    				if (AopUtils.isHashCodeMethod(method)) {
    					this.hashCodeDefined = true;
    				}
    				if (this.equalsDefined && this.hashCodeDefined) {
    					return;
    				}
    			}
    		}
    	}
    

    在创建代理时,既可以采用默认的类加载器,也可以指定特定的类加载器。JDK动态代理的代理对象是接口类型,先获取被代理对象的完整接口、根据指定的类加载器以及实现的调用处理器应用静态方法Proxy.newProxyInstance创建代理对象。

    invoke

    上文介绍了InvocationHandler 接口,invoke该接口中唯一一个定义的方法。JdkDynamicAopProxy 是final类并且实现了InvocationHandler 接口,那么也必然实现了invoke方法,其源码如下:

    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		MethodInvocation invocation;
    		Object oldProxy = null;
    		boolean setProxyContext = false;
    
    		TargetSource targetSource = this.advised.targetSource;
    		Class<?> targetClass = null;
    		Object target = null;
    
    		try {
    			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
    				return equals(args[0]);
    			}
    			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
    				return hashCode();
    			}
    			else if (method.getDeclaringClass() == DecoratingProxy.class) {
    				return AopProxyUtils.ultimateTargetClass(this.advised);
    			}
    			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
    					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
    				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
    			}
    
    			Object retVal;
    
    			if (this.advised.exposeProxy) {
    
    				oldProxy = AopContext.setCurrentProxy(proxy);
    				setProxyContext = true;
    			}
    
    			target = targetSource.getTarget();
    			if (target != null) {
    				targetClass = target.getClass();
    			}
    
    			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
    			if (chain.isEmpty()) {
    				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    			}
    			else {
    				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    				retVal = invocation.proceed();
    			}
    
    			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()) {
    				targetSource.releaseTarget(target);
    			}
    			if (setProxyContext) {
    				AopContext.setCurrentProxy(oldProxy);
    			}
    		}
    	}
    

    前面只是一些校验,直接省略,步入重点。通过target = targetSource.getTarget()得到被代理对象的类名。再根据被代理类名和方法名得到拦截链,也即通知链。如下所示:

    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    

    如果拦截链为空,则直接反射调用被代理方法,否则需要创建代理方法,此代理方法中已经加入附加处理(通知)。如下:

    			if (chain.isEmpty()) {
    				//处理被代理方法参数
    				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    				//反射执行被代理方法
    				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    			}
    			else {
    				// 创建代理方法
    				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    				// 执行代理方法
    				retVal = invocation.proceed();
    			}
    

    反射执行被代理方法是调用工具类AopUtils中方法invokeJoinpointUsingReflection实现的,具体如下:

    	public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
    			throws Throwable {
    
    		// Use reflection to invoke the method.
    		try {
    			ReflectionUtils.makeAccessible(method);
    			return method.invoke(target, args);
    		}
    		catch (InvocationTargetException ex) {
    			// Invoked method threw a checked exception.
    			// We must rethrow it. The client won't see the interceptor.
    			throw ex.getTargetException();
    		}
    		catch (IllegalArgumentException ex) {
    			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
    					method + "] on target [" + target + "]", ex);
    		}
    		catch (IllegalAccessException ex) {
    			throw new AopInvocationException("Could not access method [" + method + "]", ex);
    		}
    	}
    

    创建代理方法是通过ReflectiveMethodInvocation实现的,然后调用proceed()方法执行拦截链和被代理方法。ReflectiveMethodInvocation实现了Joinpoint接口,其构造器如下:

    	protected ReflectiveMethodInvocation(
    			Object proxy, Object target, Method method, Object[] arguments,
    			Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
    
    		this.proxy = proxy;
    		this.target = target;
    		this.targetClass = targetClass;
    		this.method = BridgeMethodResolver.findBridgedMethod(method);
    		this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
    		this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    	}
    

    ReflectiveMethodInvocation调用proceed方法执行代理,proceed方法是在Joinpoint接口中定义的,ReflectiveMethodInvocation中进行了实现。具体实现如下:

    	public Object proceed() throws Throwable {
    		//	We start with an index of -1 and increment early.
    		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    			return invokeJoinpoint();
    		}
    
    		Object interceptorOrInterceptionAdvice =
    				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    			// Evaluate dynamic method matcher here: static part will already have
    			// been evaluated and found to match.
    			InterceptorAndDynamicMethodMatcher dm =
    					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
    			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
    				return dm.interceptor.invoke(this);
    			}
    			else {
    				// Dynamic matching failed.
    				// Skip this interceptor and invoke the next in the chain.
    				return proceed();
    			}
    		}
    		else {
    			// It's an interceptor, so we just invoke it: The pointcut will have
    			// been evaluated statically before this object was constructed.
    			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    		}
    	}
    

    从上面分析源码大致可以了解Spring AOP 动态代理的设计思想,采用类加载器根据接口产生代理方法,代理方法是在原方法的基础上加上通知链,以实现AOP功能。当执行方法时,判断该方法通知链是否为空,若为空,则通过反射直接调用原方法;若不为空,则产生代理方法,执行代理方法。下一节将继续探讨Spring AOP 的另一种实现方法CGLIB

  • 相关阅读:
    win7每天出现taskeng.exe进程的解决方案
    hibernate插入中文字段时,无法插入数据库
    本页面用来演示如何通过JS SDK,创建完整的QQ登录流程,并调用openapi接口
    不同项目之间的通信
    404错误、405错误、500错误出错原因
    linux 下启动tomcat 时没有执行权限
    webservice文件上传下载(byte[] 实现方式)
    文件路径获取
    单个文件复制
    myeclipse svn重新定位 本地文件 svn 重新定位
  • 原文地址:https://www.cnblogs.com/hthuang/p/7797588.html
Copyright © 2011-2022 走看看