AbstractAutoProxyCreator#postProcessBeforeInstantiation
一、定义
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的更多相关文章
- spring异常-aoperror at :0 formal unbound in pointcut
八月 17, 2016 10:15:21 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRe ...
- 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 ...
- Pointcut is not well-formed: expecting 'identifier' at character position 0
异常如下: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDa ...
- Spring AOP报错
八月 01, 2016 10:08:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRe ...
- Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWo
1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...
- 解决 spring-cloud-starter-zipkin 启动错误
应用场景:Spring Boot 服务添加 Zipkin 依赖,进行服务调用的数据采集,然后进行 Zipkin-Server 服务调用追踪显示. 示例pom.xml配置: <parent> ...
- Spring中的AOP 专题
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
- 开发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 ...
- spring源码分析之初始化过程
1.org.springframework.web.context.ContextLoaderListener 一个ServletContextListener,web容器启动监听器 1.1内有成员C ...
- Linux下Tomcat项目启动报错
Linux下Tomcat项目启动报错 org.springframework.beans.factory.CannotLoadBeanClassException: Error loading cla ...
随机推荐
- 一款基于 .NET8 + Vue 开源、免费、跨平台的企业级在线考试系统
前言 今天大姚给大家分享一款基于 .NET8 + Vue 开源.免费(AGPL-3.0开源协议).跨平台的企业级在线考试系统:XBLMS. 项目介绍 XBLMS是一款基于 .NET8 + Vue 开源 ...
- c++:-6
上一节学习了C++中的多态性:c++:-5,本节学习C++的函数模版.数据结构以及排序查找操作: 模版 函数模版 思考:如果重载的函数,其解决问题的逻辑是一致的.函数体语句相同,只是处理的数据类型不同 ...
- .NET 9 new features-C#13新的锁类型和语义
C# 13 中,引入了新的锁类型和语义,主要用于增强多线程编程中的同步机制. 传统上,C# 使用 lock 关键字与任意的 object 实例配合,实现线程间的互斥访问.然而,这种方式可能存在性能瓶颈 ...
- 深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用
title: 深入探讨数据库索引类型:B-tree.Hash.GIN与GiST的对比与应用 date: 2025/1/26 updated: 2025/1/26 author: cmdragon ex ...
- 利用deepseek进行分析某b站是否有漏洞
以下是对 nmap -sV -O -p 80,443 --script=http-title bxxxxxxx.com 扫描结果的逐项解析和技术总结: 1. 基本信息 目标IP:139.159.241 ...
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Live View Kit (1)
1.问题描述: 客户端创建实况窗后,通过Push kit更新实况窗内容,这个过程是自动更新的还是客户端解析push消息数据后填充数据更新?客户端除了接入Push kit和创建实况窗还需要做什么工作? ...
- acwing329 围栏障碍训练场 题解
考试压轴题,意识到这题是线段树优化 \(dp\) 时追悔莫及. 为了简化题目,我将从起点到原点变成了从原点到起点(这样就可以省去两个数组的空间). 想到设 \(dp_{i,j}\) 表示在第 \(i\ ...
- STC15F104E的外部中断工作异常
STC15F104E使用了外部中断,发现中断工作有时会失效,必需重新上电才能恢复,使用中不时会失效. 1 /********************************************** ...
- kalibr标定单相机,自用指南,防忘记
1. 标定环境 1.1 从源码编译(linux环境,建议ubuntu 18或20) 步骤见 kalibr wiki 1.2 Docker 如果实体机为Ubuntu,则见official docker ...
- Flink Watermark 不止可以用时间戳衡量
https://mp.weixin.qq.com/s/L5PqtcmffCIq_CnUs0WS3g