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. javamail模拟邮箱功能发送电子邮件-中级实战篇【新增附件发送方法】(javamail API电子邮件实例)

    引言: JavaMail jar包下载地址:http://java.sun.com/products/javamail/downloads/index.html 此篇是紧随上篇文章而封装出来的,阅读本 ...

  2. 支持多种浏览器的纯css下拉菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. centos ssh 乱码

    vim /etc/sysconfig/i18n 然后把里面的LANG="zh_CN.UTF-8"改成LANG="zh_CN.GB18030"

  4. phpmyadmin 设置用户登录

    找到 /opt/lampp/phpmyadmin/config.inc.php文件修改下面配置 这是原配置 #$cfg['Servers'][$i]['auth_type'] = 'config'; ...

  5. hdu 1565(状态压缩基础题)

    题意:容易理解. 分析:这是我做的状态压缩第二题,一开始超内存了,因为数组开大了,后来超时了,因为能够成立的状态就那么多,所以你应该先把它抽出来!!总的来说还是比较简单的!! 代码实现: #inclu ...

  6. 通过HttpClient来调用Web Api接口

    回到目录 HttpClient是一个被封装好的类,主要用于Http的通讯,它在.net,java,oc中都有被实现,当然,我只会.net,所以,只讲.net中的HttpClient去调用Web Api ...

  7. go 应用程序性能测试

    runtime/pprof 我们要加入对pprof包里的方法调用,程序才能将运行时候程序的堆内存分配状态记录到文件(也可以是写到其他地方,例如网络等)中,以便进一步的分析. 如果你的go程序只是一个应 ...

  8. Raspberry Pi3 ~ 配置网络

    Rpi3 有两个网卡 一个无线wlan 一个有线 eth0 无线的只需要在右上角的那个配置里面添加就行 有线的需要设置下静态IP.dns.等 在raspbain图形化界面里面 设置 Network P ...

  9. 《Windows核心编程》第5版 学习进度备忘

    学习资源:<Windows核心编程>第5版 知识基础支持: 本书与<Windows程序设计>第5版珍藏版结合很好,二者重叠内容不多,二者互补性强,而且相关方面的优秀书籍 跳过的 ...

  10. latex公式中的空格如何表示

    两个quad空格 a \qquad b 两个m的宽度 quad空格 a \quad b 一个m的宽度 大空格 a\ b 1/3m宽度 中等空格 a\;b 2/7m宽度 小空格 a\,b 1/6m宽度 ...