Spring源码分析之AOP从解析到调用(三)

简介: Spring源码分析之AOP从解析到调用

createProxy

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
      @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  ProxyFactory proxyFactory = new ProxyFactory();
  proxyFactory.copyFrom(this);
  // 将specificInterceptors(现在是Object)转化为Advisor返回
  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  // 赋值到proxyFactory的advisors属性中
  proxyFactory.addAdvisors(advisors);
  proxyFactory.setTargetSource(targetSource);
  customizeProxyFactory(proxyFactory);
  // 创建动态代理
  return proxyFactory.getProxy(getProxyClassLoader());
}

proxyFactory.getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
  // 创建代理对象
  return createAopProxy().getProxy(classLoader);
}

createAopProxy

protected final synchronized AopProxy createAopProxy() {
  // 创建AOP代理对象
  return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  // @EnableAspectJAutoProxy的proxyTargetClass是否配置为true
  if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    Class<?> targetClass = config.getTargetClass();
    if (targetClass == null) {
      throw new AopConfigException("TargetSource cannot determine target class: " +
                                   "Either an interface or a target is required for proxy creation.");
    }
    // 如何是接口则创建jdk动态代理
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
    // cglib动态代理
    return new ObjenesisCglibAopProxy(config);
  }
  // 默认是jdk动态代理
  else {
    return new JdkDynamicAopProxy(config);
  }
}
public Object getProxy(@Nullable ClassLoader classLoader) {
  // 获取到代理的接口
  Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  // 创建jdk代理,传入的为JdkDynamicAopProxy对象,里面包含了被代理的bean以及匹配的advisor
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

动态代理创建完成~

代理对象调用过程

对象都给你创建好了,接下当然是开…发起调用咯

以下是调用的大致流程图

代理对象调用过程

代理对象被调用的是invoke方法,我们所创建的代理对象为JdkDynamicAopProxy,所以

JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  Object oldProxy = null;
  boolean setProxyContext = false;
  // 取出包装了被代理bean的对象->创建代理对象时的SingletonTargetSource, advised为ProxyFactory
  TargetSource targetSource = this.advised.targetSource;
  Object target = null;
  // 拿到bean
  target = targetSource.getTarget();
  Class<?> targetClass = (target != null ? target.getClass() : null);
  // 将所有advisor中的advice取出,并转化为对应的interceptor
  List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  // 创建一个最外层的MethodInvocation用于发起调用
  MethodInvocation invocation =
    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  // 发起链式调用
  Object retVal = invocation.proceed();
  return retVal;
}

我们先看获取interceptor的过程

getInterceptorsAndDynamicInterceptionAdvice

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
  // 将所有advisor中的advice取出并封装成intercept
  return this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  Advised config, Method method, @Nullable Class<?> targetClass) {
  // 创建一个advisor适配器的注册器用于转化advice,创建时将默认注册三个适配器
  AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  Advisor[] advisors = config.getAdvisors();
  // 循环遍历所有advisor
  for (Advisor advisor : advisors) {
    // 将advisor中的advice转化为interceptor
    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
    interceptorList.addAll(Arrays.asList(interceptors));
    return interceptorList;
  }
}

GlobalAdvisorAdapterRegistry.getInstance() 类初始化时调用静态方法

private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry()
public static AdvisorAdapterRegistry getInstance() {
    return instance;
}
public DefaultAdvisorAdapterRegistry() {
  // 注册三个适配器
  registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
  registerAdvisorAdapter(new AfterReturningAdviceAdapter());
  registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
  // 将适配器加入集合
  this.adapters.add(adapter);
}

registry.getInterceptors 这里面包含了advice转化成interceptor的过程

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
  List<MethodInterceptor> interceptors = new ArrayList<>(3);
  Advice advice = advisor.getAdvice();
  // advice本身是否就是MethodInterceptor
  if (advice instanceof MethodInterceptor) {
    interceptors.add((MethodInterceptor) advice);
  }
  for (AdvisorAdapter adapter : this.adapters) {
    // 判断advice是哪个advice 如:(advice instanceof MethodBeforeAdvice)
    if (adapter.supportsAdvice(advice)) {
      // 将advice封装到对应的interceptor
      interceptors.add(adapter.getInterceptor(advisor));
    }
  }
  return interceptors.toArray(new MethodInterceptor[0]);
}

若adapter为MethodBeforeAdviceAdapter,则

public MethodInterceptor getInterceptor(Advisor advisor) {
  MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
  return new MethodBeforeAdviceInterceptor(advice);
}

其他advice转化过程相同

以上,便将所有的advice转化成了interceptor,接下来,则是经典的链式递归调用过程

以下过程小伙伴们可以对照流程图阅读,毕竟递归还是有些复杂,需要一定的功底

ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {
  // currentInterceptorIndex 初始值为-1
  // 当currentInterceptorIndex等于advice的数量减一时,则调用目标方法
  // 由于advice已排好序,所以调用顺序为before, after, afterReturn, afterThrowing
  // 注意,并非调用到相应的advice就会执行advice方法,这里是类似递归调用的方式,会存在一个归过程
  // 有些是递的时候发起调用,如beforeAdvice, 但有些则是归的时候发起调用,如afterAdvice
  // 递归的终止条件则是这下面这个return invokeJoinpoint();
  if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return invokeJoinpoint();
  }
  // currentInterceptorIndex自增并获取到interceptor
  Object interceptorOrInterceptionAdvice =
    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  // 将interceptro强转为MethodInterceptor发起调用
  return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}

此时currentInterceptorIndex值为0,而我们的advice为4个(去除了默认的),所以当currentInterceptorIndex为3时便会调用我们的实际方法

首先调用的是MethodBeforeAdviceInterceptor

public Object invoke(MethodInvocation mi) throws Throwable {
  // 调用前置通知
  this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
  return mi.proceed();
}

mi为传入的this,所有mi.proceed()将会回到最开始的方法

再次循环,此时currentInterceptorIndex值为1

调用的是AspectJAfterAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
  try {
    return mi.proceed();
  }
  finally {
    // finally意味着不管怎样都会被调用
    invokeAdviceMethod(getJoinPointMatch(), null, null);
  }
}

继续,此时currentInterceptorIndex值为2

调用的是AfterReturningAdviceInterceptor

public Object invoke(MethodInvocation mi) throws Throwable {
  Object retVal = mi.proceed();
  this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
  return retVal;
}

继续,此时currentInterceptorIndex值为3

调用的是AspectJAfterThrowingAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
  try {
    return mi.proceed();
  }
  catch (Throwable ex) {
    if (shouldInvokeOnThrowing(ex)) {
      // 调用异常通知
      invokeAdviceMethod(getJoinPointMatch(), null, ex);
    }
    // 往外抛出异常
    throw ex;
  }
}

所以如果我们的业务方法发生了异常,会调用到异常通知,而这里又把异常往外抛,所以afterReturn就会被跳过直接到after的finally方法

现在currentInterceptorIndex值为3了,再回调最初的方法中时,就会调用到我们的业务方法了。调用完毕则进行归的过程,调用过程便结束了。

以上,便是整个AOP的过程了,下一篇,事务相关源码解析~

本篇文章中涉及到图片的矢量图地址为:https://www.processon.com/view/link/5fa8afdae401fd45d109f257,有需要的小伙伴可自取

目录
相关文章
|
6月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
6月前
|
缓存 安全 Java
Spring Security通用权限管理模型解析
Spring Security作为Spring生态的核心安全框架,结合RBAC与ACL权限模型,基于IoC与AOP构建灵活、可扩展的企业级权限控制体系,涵盖认证、授权流程及数据库设计、性能优化等实现策略。
449 0
|
6月前
|
缓存 安全 Java
Spring Security权限管理解析
Spring Security是Spring生态中的核心安全框架,采用认证与授权分离架构,提供高度可定制的权限管理方案。其基于过滤器链实现认证流程,通过SecurityContextHolder管理用户状态,并结合RBAC模型与动态权限决策,支持细粒度访问控制。通过扩展点如自定义投票器、注解式校验与前端标签,可灵活适配多租户、API网关等复杂场景。结合缓存优化与无状态设计,适用于高并发与前后端分离架构。
461 0
|
6月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
2200 0
|
6月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
673 0
|
6月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
637 0
|
5月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
5月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
6月前
|
Java 数据库 数据安全/隐私保护
Spring Boot四层架构深度解析
本文详解Spring Boot四层架构(Controller-Service-DAO-Database)的核心思想与实战应用,涵盖职责划分、代码结构、依赖注入、事务管理及常见问题解决方案,助力构建高内聚、低耦合的企业级应用。
1280 1

推荐镜像

更多
  • DNS