一、定义

postProcessBeforeInstantiation 是 Spring AOP 动态代理的核心扩展点,通过提前创建代理对象优化性能,并支持丰富的自定义逻辑(如事务、安全)

二、代码分析

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {

		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
} // Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
} return null;
}

1、生成缓存键

  • 作用: 根据 Bean 的类名或 Bean 名称生成唯一的缓存键,用于后续缓存操作

2、检查是否需要处理当前 Bean

  • 作用: 确定当前 Bean 是否已经被处理过

  • 条件解释:

    • beanName == null: 处理匿名 Bean。

    • !targetSourcedBeans.contains(beanName): 确保 Bean 未被标记为已处理。

  • 集合说明: targetSourcedBeans: 记录已通过自定义 TargetSource 处理的 Bean,避免重复代理

3、查是否已处理 或 需跳过

  • 分支 1: 如果缓存键已经存在于advisedBeans中,直接返回null。这说明这个Bean已经被处理过,不需要再次处理,直接跳过

  • 分支 2:

    • isInfrastructureClass(beanClass): 判断是否为 Spring 内部类(如 Advisor, Advice),实现逻辑: 检查类是否实现 Advice、Advisor 等接口

    • shouldSkip(beanClass, beanName): 根据用户配置或注解(如 @SkipAop)决定跳过代理

    • 标记为不代理: 将 cacheKey 对应值设为 FALSE,避免重复检查

4、处理自定义 TargetSource

  • 作用: 检查是否有自定义的 TargetSource,若有则创建代理。

  • getCustomTargetSource 逻辑:

    • 查找 Bean 定义中是否指定了 TargetSource。

    • 示例:通过 @Scope 配置 proxyMode 或 XML 中定义 target-source 属性。

  • 示例场景:

    • 动态数据源切换: 根据请求上下文动态选择数据源实现。

5、创建代理对象

  • 步骤详解:

    • 1、标记为已处理: 将 beanName 加入 targetSourcedBeans。

    • 2、获取拦截器:

      • getAdvicesAndAdvisorsForBean: 收集匹配该 Bean 的所有拦截器(如事务、日志 Advice)。

      • 匹配逻辑: 根据切点表达式(Pointcut)判断拦截器是否适用

    • 3、生成代理:

      • createProxy: 根据配置选择 JDK 动态代理或 CGLIB。

        • JDK 代理: Bean 实现至少一个接口。

        • CGLIB 代理: Bean 无接口或强制使用 CGLIB。

      • 参数 SingletonTargetSource: 确保代理持有单例目标对象

6、默认返回 null

  • 作用: 若无自定义 TargetSource 或无需代理,返回 null,触发 Spring 默认实例化流程。

  • 后续流程: Spring 将调用构造器创建 Bean,进行属性注入和初始化。

AbstractAutoProxyCreator#postProcessBeforeInstantiation的更多相关文章

  1. spring异常-aoperror at :0 formal unbound in pointcut

    八月 17, 2016 10:15:21 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRe ...

  2. Java AOP nested exception is java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice || Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#0' 两个异常解决办法

    贴出applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...

  3. Pointcut is not well-formed: expecting 'identifier' at character position 0

    异常如下: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDa ...

  4. Spring AOP报错

    八月 01, 2016 10:08:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRe ...

  5. Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWo

    1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...

  6. 解决 spring-cloud-starter-zipkin 启动错误

    应用场景:Spring Boot 服务添加 Zipkin 依赖,进行服务调用的数据采集,然后进行 Zipkin-Server 服务调用追踪显示. 示例pom.xml配置: <parent> ...

  7. Spring中的AOP 专题

    Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...

  8. 开发Spring过程中几个常见异常(二):Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'a' define

    本异常是小编在运行自己另外一篇博文中的例子时遇到的.(附博文:http://www.cnblogs.com/dudududu/p/8482487.html) 完整异常信息: 警告: Exception ...

  9. spring源码分析之初始化过程

    1.org.springframework.web.context.ContextLoaderListener 一个ServletContextListener,web容器启动监听器 1.1内有成员C ...

  10. Linux下Tomcat项目启动报错

    Linux下Tomcat项目启动报错 org.springframework.beans.factory.CannotLoadBeanClassException: Error loading cla ...

随机推荐

  1. 深入理解第一范式(1NF):数据库设计中的基础与实践

    title: 深入理解第一范式(1NF):数据库设计中的基础与实践 date: 2025/1/15 updated: 2025/1/15 author: cmdragon excerpt: 在关系型数 ...

  2. MongoDB:文档基本CRUD

  3. Map 实现类之:TreeMap(SortedMap的实现类) 和 Properties(Hashtable的实现类)

    TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序.TreeMap 可以保证所有的 Key-Value 对处于 有序状态.TreeSet底层使用 红黑树结构存储 ...

  4. 设置npm、yarn和pnpm的国内镜像地址和yarn命令相关问题

    1.npm 全局设置: 输入如下命令查看镜像地址: npm config get registry 输入如下命令设置镜像地址为淘宝: // 推荐地址 npm config set registry h ...

  5. 让我们从零开始使用PyTorch构建一个轻量级的词嵌入模型

    图片来源:Phil Hearing(Unsplash) 在我之前写的一篇文章中,我们学习了如何使用PyTorch的nn.Embedding层将单词转换为稠密向量.但由于该嵌入层是未经训练的,这些向量并 ...

  6. deepseek-v3 论文阅读

    模型结构 MLA(Multi-Head Latent Attention) 主要作用是在保证效果的基础上, 利用低秩压缩的原理优化kvCache, 加速推理, 同时节省训练显存. 先回忆下MHA, 在 ...

  7. AI-启动

    前言 我们都知道AI可以帮助我们完成很多工作,同时也可以帮助我们快速生成一些繁琐的文档:本篇介绍接入一些开源的大预言模型: 准备 OpenAPI 首先需要了解下什么是OpenAPI,OpenAPI是一 ...

  8. go测试跨包代码覆盖率

    Golang虽然只是一门编程语言,但也为我们提供了不少工具,其中测试工具是最常用的,大概 前提概要 以前看书,只说了用什么工具去做覆盖率,和基本的使用,当时看了也没想太多.后面真正做项目了,老大要求比 ...

  9. 自适应 Simpson 积分法学习笔记

    自适应 Simpson 积分法,是一种计算一段区间内,形态奇怪的函数和的算法,例如面积并和难以直接用通项公式计算的函数. Simpson 积分 我们都知道,求解微积分需要求解一个导数的原函数,但这显然 ...

  10. deepseek:以php为例,获取令牌后下一步处理步骤

    在 PHP 中,获取到 Bearer Token 后,下一步通常是验证令牌的有效性,并根据令牌中的信息处理请求.以下是详细的步骤和代码示例: 1. 获取 Authorization 头中的令牌 首先, ...