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. c# datagridview表格控件常用操作

    1) 行右键菜单 private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e) { ...

  2. WORD中如何让前两页不显示页码

    WORD中如何让前两页不显示页码   上稿人:ojn 点击率: 15191   我们有时在用word编辑文档时,会遇上第一.二页无需显示页码,第三页才是正文的第一页时,该如何正确插入页码呢? 以wor ...

  3. @Component @Repository @Service @Controller

    Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository.@Service 和 @Controller.在目前的 Spring ...

  4. DevExpress 14.2.3源码编译 z

    一.准备 1.准备一台Windows 8.1机器,安装VS2013 2.准备一台Windows 8.1机器,安装VS2010    XP的系统肯定不行,因为有不少的运行库不支持     Windows ...

  5. Chopsticks

    题意: n个数3个相邻是一组,求选k组使得,各组组内较小的两个数的差之和最小. 分析: 对于每个数选或不选的问题,dp[i][j]表前i个数选了j组得到的最小和. dp[i][j]=min(dp[i- ...

  6. OpenERP中的会计凭证

    OpenERP在采购和销售过程中会自动生成一些会计凭证,这些会计凭证反映了物流和资金流在财务上的处理方式. 仓库入库时 借:库存商品 贷:在途物资 收到供应商发票时 借:在途物资 借:进项税额 贷:应 ...

  7. LoadRunner error -27257

    检查点函数 web_reg_find("Search=body", "savecount=num", "Text=test1", LAST) ...

  8. 如何查看python selenium的api

    1. 打开命令行: command+R2. 输入: python -m pydoc -p 4567,然后:Enter3. 然后在浏览器中访问http://localhost:45674. 按ctrl+ ...

  9. C# 实现无焦点窗体(转载)

    #region 无焦点窗体 [System.Runtime.InteropServices.DllImport("user32.dll")] private extern stat ...

  10. MFC CString的L和_T

    这个问题困扰了很久,这个解释貌似好理解一些 L表示UNICODE串,比如wchar_t* str = L"yangsongx";_T在ANSI编译模式下表示ANSI串,在UNICO ...