JdkDynamicAopProxy是通过接口实现动态代理类,主要方法是getProxy(ClassLoader classLoader), 代理类生成之后再调用目标方法时就会调用invoke方法。

package org.springframework.aop.framework;
 
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
 
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 
import org.springframework.aop.AopInvocationException;
import org.springframework.aop.RawTargetAccess;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
 
/**
 * JDK-based {@link AopProxy} implementation for the Spring AOP framework,
 * based on JDK {@link java.lang.reflect.Proxy dynamic proxies}.
 *
 * <p>Creates a dynamic proxy, implementing the interfaces exposed by
 * the AopProxy. Dynamic proxies <i>cannot</i> be used to proxy methods
 * defined in classes, rather than interfaces.
 *
 * <p>Objects of this type should be obtained through proxy factories,
 * configured by an {@link AdvisedSupport} class. This class is internal
 * to Spring's AOP framework and need not be used directly by client code.
 *
 * <p>Proxies created using this class will be thread-safe if the
 * underlying (target) class is thread-safe.
 *
 * <p>Proxies are serializable so long as all Advisors (including Advices
 * and Pointcuts) and the TargetSource are serializable.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Dave Syer
 * @see java.lang.reflect.Proxy
 * @see AdvisedSupport
 * @see ProxyFactory
 */
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
 
 /** use serialVersionUID from Spring 1.2 for interoperability */
 private static final long serialVersionUID = 5531744639992436476L;
 
 
 /*
  * NOTE: We could avoid the code duplication between this class and the CGLIB
  * proxies by refactoring "invoke" into a template method. However, this approach
  * adds at least 10% performance overhead versus a copy-paste solution, so we sacrifice
  * elegance for performance. (We have a good test suite to ensure that the different
  * proxies behave the same :-)
  * This way, we can also more easily take advantage of minor optimizations in each class.
  */
 
 /** We use a static Log to avoid serialization issues */
 private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
 
 /** Config used to configure this proxy */
 private final AdvisedSupport advised;
 
 /**
  * Is the {@link #equals} method defined on the proxied interfaces?
  */
 private boolean equalsDefined;
 
 /**
  * Is the {@link #hashCode} method defined on the proxied interfaces?
  */
 private boolean hashCodeDefined;
 
 
 /**
  * Construct a new JdkDynamicAopProxy for the given AOP configuration.
  * @param config the AOP configuration as AdvisedSupport object
  * @throws AopConfigException if the config is invalid. We try to throw an informative
  * exception in this case, rather than let a mysterious failure happen later.
  */
 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;
 }
 
 
 @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);
  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;
    }
   }
  }
 }
 
 
 /**
  * Implementation of {@code InvocationHandler.invoke}.
  * <p>Callers will see exactly the exception thrown by the target,
  * unless a hook method throws an exception.
  */
 @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)) {
    // The target does not implement the equals(Object) method itself.
    return equals(args[0]);
   }
   if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
    // The target does not implement the hashCode() method itself.
    return hashCode();
   }
   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;
   }
 
   // May be null. Get as late as possible to minimize the time we "own" the target,
   // in case it comes from a pool.
   target = targetSource.getTarget();
   if (target != null) {
    targetClass = target.getClass();
   }
 
   // Get the interception chain for this method.
   List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
 
   // Check whether we have any advice. If we don't, we can fallback on direct
   // reflective invocation of the target, and avoid creating a MethodInvocation.
   if (chain.isEmpty()) {
    // We can skip creating a MethodInvocation: just invoke the target directly
    // Note that the final invoker must be an InvokerInterceptor so we know it does
    // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
   }
   else {
    // We need to create a method invocation...
    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.isInstance(proxy) &&
     !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
    // Special case: it returned "this" and the return type of the method
    // is type-compatible. Note that we can't help if the target sets
    // a reference to itself in another returned object.
    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);
   }
  }
 }
 
 
 /**
  * Equality means interfaces, advisors and TargetSource are equal.
  * <p>The compared object may be a JdkDynamicAopProxy instance itself
  * or a dynamic proxy wrapping a JdkDynamicAopProxy instance.
  */
 @Override
 public boolean equals(Object other) {
  if (other == this) {
   return true;
  }
  if (other == null) {
   return false;
  }
 
  JdkDynamicAopProxy otherProxy;
  if (other instanceof JdkDynamicAopProxy) {
   otherProxy = (JdkDynamicAopProxy) other;
  }
  else if (Proxy.isProxyClass(other.getClass())) {
   InvocationHandler ih = Proxy.getInvocationHandler(other);
   if (!(ih instanceof JdkDynamicAopProxy)) {
    return false;
   }
   otherProxy = (JdkDynamicAopProxy) ih;
  }
  else {
   // Not a valid comparison...
   return false;
  }
 
  // If we get here, otherProxy is the other AopProxy.
  return AopProxyUtils.equalsInProxy(this.advised, otherProxy.advised);
 }
 
 /**
  * Proxy uses the hash code of the TargetSource.
  */
 @Override
 public int hashCode() {
  return JdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
 }
 
}
 

JdkDynamicAopProxy源码的更多相关文章

  1. SpringAop源码情操陶冶-JdkDynamicAopProxy

    承接前文SpringAop源码情操陶冶-AspectJAwareAdvisorAutoProxyCreator,本文在前文的基础上稍微简单的分析默认情况下的AOP代理,即JDK静态代理 JdkDyna ...

  2. spring源码分析(二)Aop

    创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...

  3. Spring源码学习(二)AOP

    ----ProxyFactoryBean这个类,这是AOP使用的入口---- AOP有些特有的概念,如:advisor.advice和pointcut等等,使用或配置起来有点绕,让人感觉有些距离感,其 ...

  4. Spring核心框架 - AOP的原理及源码解析

    一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置A ...

  5. AOP执行增强-Spring 源码系列(5)

    AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...

  6. SpringAop源码情操陶冶-AspectJAwareAdvisorAutoProxyCreator

    本文将对SpringAop中如何为AspectJ切面类创建自动代理的过程作下简单的分析,阅读本文前需要对AOP的Spring相关解析有所了解,具体可见Spring源码情操陶冶-AOP之ConfigBe ...

  7. Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程

    spring-aop-4.3.7.RELEASE  在<Spring AOP高级——源码实现(1)动态代理技术>中介绍了两种动态代理技术,当然在Spring AOP中代理对象的生成也是运用 ...

  8. 异步任务spring @Async注解源码解析

    1.引子 开启异步任务使用方法: 1).方法上加@Async注解 2).启动类或者配置类上@EnableAsync 2.源码解析 虽然spring5已经出来了,但是我们还是使用的spring4,本文就 ...

  9. Spring提取@Transactional事务注解的源码解析

    声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记: 难免有错误,敬请读者谅解!!! 1.事务注解标签 <tx:annotation-driven /> 2.tx 命名空间 ...

随机推荐

  1. webservices上传文件

    客户端: ob_clean(); ob_start(); readfile("D:/44.jpg"); $logo = ob_get_clean(); $pararmArr = a ...

  2. SAS9.4 安装注意事项

    OS:Windows Server 2012 R2 SAS:9.4 TS1M1 SAS9.4的安装需要注意的地方: 一. 注意开启Shortname(装了N遍,最容易忘记的地方) SAS安装使用Sho ...

  3. ubuntu下安装Matlab

    (注:本文部分内容转自互联网) 一. 安装程序Step 1:下载matlab的安装文件至主目录下,讲matlab文件重命名为Mathworks.Matlab.R2012a.Unix.isoStep 2 ...

  4. PHP的cURL库:抓取网页,POST数据及其他,HTTP认证 抓取数据

    From : http://developer.51cto.com/art/200904/121739.htm 下面是一个小例程: ﹤?php// 初始化一个 cURL 对象$curl = curl_ ...

  5. arcgis9.3 执行python文件

    1) 打开Python GUI 2) 选择菜单“File->Open”,打开你要执行的*.py文件 3) 选择菜单“Run->Run Module”,运行python文件 4)运行结果

  6. swfupload 参数说明

    一.配置参数对象中的常用属性及说明 属性 类型 默认值 描述 upload_url String   处理上传文件的服务器端页面的url地址,可以是绝对地址,也可以是相对地址,当为相对地址时相对的是当 ...

  7. Nginx - Windows下Nginx基本安装和配置

    Nginx 是一个轻量级的高性能 Http WebServer,以事件驱动方式编写,因此相比 Apache 而言,Nginx 更加稳定.性能更好,而且配置简单,资源占用较低. 1. 安装 Nginx ...

  8. linux grub

    grub 是目前使用最广泛的linux引导装载程序,旧的lilo这个引导装载程序很少见了,grub优点: 支持较多哦的文件系统,可以使用grub主程序在文件系统中查找内核文件名 启动的时候,可以自行编 ...

  9. git 操作大全

    Git 以下内容整理自廖雪峰的git教程,主要用于个人方便使用git命令 git忽略已经被纳入版本库的文件 使用 git update-index –-skip-worktree [file] 可以实 ...

  10. matlab的&amp;和&amp;&amp;操作

    A&B(1)首先判断A的逻辑值,然后判断B的值,然后进行逻辑与的计算.(2)A和B可以为矩阵(e.g. A=[1 0],B=[0 0]).A&&B(1)首先判断A的逻辑值,如果 ...