知识点:
1.初始化Bean单例池 完成getBean createBean(1)
知识点 |
核心内容 |
重点 |
单例词初始化 |
在容器初始化阶段预先创建单例对象,避免在getBean时动态创建 |
单例词必须在容器初始化时完成加载,否则会触发异常 |
getBean方法逻辑 |
1. 从beanDefinitionMap查询BeanDefinition 2. 根据scope判断单例/多例 3. 单例:直接从单例词获取 4. 多例:反射动态创建新对象 |
多例模式每次调用getBean都会生成新实例,需与单例严格区分 |
异常处理机制 |
未找到BeanDefinition时抛出异常(如空指针),单例词缺失需检查初始化代码 |
异常类型选择需符合业务逻辑,单例词完整性是关键验证点 |
反射创建对象 |
通过BeanDefinition中的Class对象反射实例化,支持多例模式动态生成 |
反射性能开销较高,需注意多例场景的并发控制 |
流程图解逻辑 |
1. 查询BeanDefinition → 2. 判断scope → 3. 单例词/反射分支处理 |
分支优先级:单例词检查 > 多例创建 > 异常兜底 |
2.初始化Bean单例池 完成getBean createBean(2)
知识点 |
核心内容 |
重点 |
反射创建对象 |
通过bin definition对象动态创建实例,使用getDeclaredConstructor()和newInstance()实现反射 |
构造器参数处理(当前未实现,但预留扩展) |
方法设计逻辑 |
createBin方法返回Object类型,兼容未知返回类型场景 |
异常处理(反射失败返回null) |
命名规范 |
修改名称bin definition by scan以增强可读性 |
作用域(scope)与Class对象的关联理解 |
代码分层思想 |
区分单例初始化与动态实例化场景 |
反射底层一致性(单例/多例均依赖反射) |
3.初始化Bean单例池 完成getBean createBean(3)
知识点 |
核心内容 |
重点 |
单例池初始化 |
通过反射创建bean实例并初始化单例池 |
单例与多例(prototype)的判断逻辑 |
BeanDefinition解析 |
从BeanDefinitionMap获取bean定义信息 |
getScope()方法获取作用域类型 |
集合遍历技术 |
使用Enumeration遍历Map集合 |
hasMoreElements()和nextElement()方法使用 |
依赖注入时机 |
容器创建完成后立即初始化单例bean |
构造器执行时机与扫描完成标志 |
命名规范处理 |
bean名称大小写忽略的兼容处理 |
默认命名规则与自定义名称冲突 |
测试验证方法 |
通过单例池objects集合验证实例化结果 |
动态修改bean名称的测试技巧 |
4.初始化Bean单例池 完成getBean createBean(4)
知识点 |
核心内容 |
重点 |
getBin方法实现 |
根据bean名称从单例池或创建新实例返回对象 |
单例与多实例的判断逻辑(scope值比较) |
单例模式处理 |
从singletonObjects直接获取已创建实例 |
必须确保单例bean已预先存入单例池 |
原型模式处理 |
每次调用createBean创建新实例 |
反射生成对象的性能消耗 |
异常处理机制 |
不存在的bean抛出NullPointerException |
可扩展为自定义异常类型 |
scope配置验证 |
未配置scope时默认单例模式 |
prototype配置导致每次获取不同实例 |
类型转换处理 |
Object返回值需要显式类型转换 |
类型安全校验缺失风险 |
容器初始化验证 |
beanDefinitionMap必须预先加载定义 |
定义缺失会导致空指针异常 |
测试用例设计 |
通过重复获取验证单例/原型效果 |
边界测试(不存在的bean名) |
5.实现依赖注入(1)
知识点 |
核心内容 |
重点 |
依赖注入概念 |
组件间存在依赖关系时由Spring容器自动装配属性 |
区分@Autowired按名称注入与按类型注入的区别 |
注解实现 |
自定义@Autowired注解实现依赖注入功能 |
注解修饰字段与setter方法的区别 |
反射机制应用 |
通过Class对象获取字段并检查注解修饰情况 |
字段访问权限处理与类型匹配验证 |
容器扩展点 |
在createBean方法中植入依赖注入逻辑 |
属性注入时机(实例化后/初始化前) |
装配策略 |
默认按名称匹配的依赖解析机制 |
循环依赖的检测与处理 |
6.实现依赖注入(2)
知识点 |
核心内容 |
重点 |
自定义注解实现 |
创建@AutoWired注解实现依赖注入功能 |
注解属性required的作用与默认值设置 |
依赖注入机制 |
通过容器完成字段属性自动装配 |
按名称匹配与其他匹配方式的区别 |
注解作用域控制 |
限定注解仅作用于字段(FIELD) |
原生注解功能裁剪策略 |
空指针异常验证 |
未注入时调用方法抛出NullPointerException |
异常触发条件与调试方法 |
测试验证流程 |
通过hi()方法验证注入结果 |
服务层与DAO层调用链验证 |
7.实现依赖注入(3)
知识点 |
核心内容 |
关键代码/操作 |
难点 |
反射机制应用 |
通过反射遍历类字段并处理注解 |
getDeclaredFields()获取所有字段 isAnnotationPresent(AutoWired.class)检查注解 |
私有字段访问需调用setAccessible(true)进行爆破 |
依赖注入实现 |
按名称自动装配对象 |
getBean(fieldName)获取依赖对象 field.set(instance, bean)注入属性 |
多实例与单例处理逻辑差异 |
注解属性处理 |
解析@AutoWired的required属性 |
getAnnotation(AutoWired.class).required()获取配置值 |
required=true时必须成功注入的校验逻辑 |
异常处理机制 |
非法访问异常解决方案 |
字段爆破代码示例: declaredField.setAccessible(true) |
反射操作中的权限控制要点 |
对象装配流程 |
完整依赖注入链路 |
1. 字段扫描→2. 注解检查→3. 实例获取→4. 属性设置 |
循环依赖问题的潜在风险 |
8.实现BeanPostProcessor机制(1)
知识点 |
核心内容 |
重点 |
Spring 依赖注入 |
实现任务阶段四的依赖注入机制 |
容器管理对象的生命周期 |
Bean 后置处理器 |
实现 BeanPostProcessor 接口的两个核心方法:postProcessBeforeInitialization 和 postProcessAfterInitialization |
方法调用时机(初始化前后)和 作用范围(针对所有 Bean) |
原生 Spring 后置处理器案例 |
通过 IDE 演示原生后置处理器的配置与使用 |
接口方法重写的业务逻辑实现 |
自定义 Bean 后置处理器 |
实现 Spring 扩展功能的核心机制,支持多后置处理器链式调用 |
处理顺序 和 容器集成逻辑 |
AOP 机制铺垫 |
后置处理器完成后将进入 AOP 功能开发 |
与后置处理器的关联性 |
9.实现BeanPostProcessor机制(2)
知识点 |
核心内容 |
重点 |
Spring后置处理器机制 |
通过InitializingBean接口实现初始化方法,在setter方法后调用afterPropertiesSet() |
初始化方法执行时机(setter后 vs. 后置处理器before/after方法) |
Bean生命周期阶段 |
构造器→setter→初始化方法→后置处理器after方法 |
无初始化方法时后置处理器仍会执行before/after |
接口InitializingBean作用 |
提供afterPropertiesSet()方法,等价于XML配置的init-method |
需实现接口 vs. XML配置的灵活性对比 |
后置处理器与初始化方法关系 |
后置处理器before在初始化方法前执行,after在之后执行 |
执行顺序逻辑(容器自动调用) |
代码实现示例 |
MonsterService实现InitializingBean并重写afterPropertiesSet() |
方法调用由容器控制(非主动调用) |
10.实现BeanPostProcessor机制(3)
知识点 |
核心内容 |
重点 |
接口编程概念 |
通过判断类是否实现特定接口来决定是否执行业务逻辑 |
标记接口(无方法的接口)与普通接口的区别 |
instanceof操作符 |
判断对象运行类型是否为某类型或其子类型 |
接口实现类也属于接口的子类型 |
Spring容器初始化机制 |
在bean实例化后通过InitializingBean接口执行afterPropertiesSet()方法 |
初始化时机(在set方法执行完毕后) |
标记接口应用 |
Serializable等无方法接口的底层判断用途 |
标记接口与普通功能接口的设计差异 |
类型转换与异常处理 |
将bean实例强制转换为接口类型调用初始化方法 |
ClassCastException风险处理 |
容器生命周期控制 |
在createBean方法中实现初始化逻辑判断 |
反射机制与接口回调的结合应用 |
11.实现BeanPostProcessor机制(4)
知识点 |
核心内容 |
重点 |
Bean后置处理器概念 |
介绍如何自定义实现Spring的BeanPostProcessor接口 |
接口的两个默认方法区别(before/after initialization) |
postProcessBeforeInitialization方法 |
在bean初始化方法前调用的拦截逻辑 |
方法执行时机与AOP切面编程的关系 |
postProcessBeforeInitialization方法 |
在bean初始化方法后调用的拦截逻辑 |
返回值处理与bean生命周期关系 |
后置处理器注册机制 |
必须通过@Component注解将处理器注册为Spring bean |
未注册时的表现与错误排查 |
原生Spring对比 |
演示自定义实现与原生BeanPostProcessor的异同点 |
方法签名一致性要求 |
切面编程概念 |
后置处理器对所有bean生效的切面特性 |
与AspectJ注解方式的区别 |
12.实现BeanPostProcessor机制(5)
知识点 |
核心内容 |
重点 |
后置处理器机制 |
Spring容器中后置处理器的实现逻辑与多实例管理 |
多个后置处理器的注入与调用顺序 |
接口实现判断 |
使用Class.isAssignableFrom()而非instanceof判断类对象是否实现接口 |
类对象 vs 实例对象的判断方法差异 |
容器简化设计 |
将后置处理器单独存入ArrayList而非原生单例池 |
简化逻辑与原Spring容器的差异 |
动态加载逻辑 |
在scan方法中识别并实例化后置处理器组件 |
@Component与后置处理器的特殊处理 |
集合管理策略 |
通过binPostProcessorList集中管理后置处理器实例 |
集合与单例池的取舍逻辑 |
13.实现BeanPostProcessor机制(6)
知识点 |
核心内容 |
重点 |
Spring容器初始化机制 |
后置处理器(BeanPostProcessor)在Bean初始化方法前后的调用逻辑(before/after方法) |
before方法可修改Bean实例并返回新对象,after方法同理 |
Bean生命周期控制 |
在createBean方法中实现初始化方法前后的拦截逻辑 |
初始化方法调用顺序:后置处理器before → 初始化方法 → 后置处理器after |
后置处理器实现细节 |
通过遍历BeanPostProcessor集合动态处理Bean实例 |
易混淆点:后置处理器需避免重复注册(单例池与ArrayList的冲突) |
简化容器设计 |
使用ArrayList替代单例池存储后置处理器以降低复杂度 |
关键优化:跳过冗余的create方法调用 |
调试与验证 |
通过断点调试验证后置处理器调用链的正确性 |
重点:确保before/after方法返回值正确处理Bean实例 |
14.实现BeanPostProcessor机制(7)
知识点 |
核心内容 |
重点 |
Spring后置处理器 |
通过实现InitializingBean接口和配置@Component验证car类的初始化方法及后置处理器调用逻辑 |
后置处理器的before方法针对容器内所有Bean生效,需注意作用范围与类型判断逻辑 |
切面编程概念 |
后置处理器可对多个对象操作(如统一处理car类),实现类似AOP的切面功能 |
与普通对象编程的区别:切面编程的核心是跨对象操作(如日志、权限、事务等) |
类型判断与动态处理 |
在后置处理器中通过instanceof判断car类型并单独处理,演示类型转换与方法调用 |
动态处理时机:需明确在before方法中处理还是在初始化后处理 |
Spring容器机制 |
验证@Component注解的自动装配及InitializingBean接口的初始化回调 |
易混淆点:initializingBean接口与@PostConstruct注解的优先级差异 |
业务逻辑分层 |
演示如何在后置处理器中分门别类处理不同Bean(如car与monsterService) |
关键逻辑:通过条件分支实现差异化处理,避免全量拦截影响性能 |
15.实现BeanPostProcessor机制(8)
知识点 |
核心内容 |
重点 |
Spring容器配置方式 |
通过XML或注解配置Spring容器,理解底层机制可提升掌控力 |
@Autowired注解的底层实现 vs 表面使用 |
Bean装配原理 |
从BeanPostProcessor到createBean的调用链,需传递beanName参数 |
方法参数顺序错误导致编译报错 |
调试技巧 |
通过IDE错误定位(红线提示)快速修复参数传递问题 |
beanName传递位置(需与createBean定义一致) |
16.实现BeanPostProcessor机制(9)
知识点 |
核心内容 |
重点 |
后置处理器机制 |
讲解Spring后置处理器对Bean实例的处理逻辑,包括空值返回时的容错机制 |
空值处理逻辑(原生Spring容器自动回退到原实例) |
源码调试技巧 |
通过Debug演示后置处理器before方法的执行流程,分析current对象判空逻辑 |
断点追踪时机(需关注return null时的分支跳转) |
代码改进实践 |
手动实现类似Spring的判空容错逻辑:if(current!=null) then modify instance |
自定义容器与原生的差异(需显式判空避免NPE) |
AOP关联机制 |
提及后置处理器与AOP的协同关系(未展开) |
扩展点(需结合后续AOP机制理解) |