学习日记-spring-day46-7.11
知识点:
1.实现AOP机制(1)
知识点 | 核心内容 | 重点 |
AOP机制实现原理 | 通过后置处理器和动态代理实现,在after方法中返回代理对象而非原生对象 | 代理对象生成时机(后置处理器阶段) vs 原生对象创建 |
切面类组成要素 | 需包含@Component和@Aspect注解,含@Before/@After等通知注解 | 切面类双重身份(组件+切面)的注解配置 |
代理机制调用流程 | 代理对象执行时触发前置通知→目标方法→返回通知/异常通知→最终通知 | 原生方法调用 vs 代理链式调用 |
后置处理器关键作用 | BeanPostProcessor的after方法实现代理对象替换,为AOP核心支撑 | 后置处理器与IOC容器的协作时序 |
动态代理技术选择 | JDK动态代理(接口级)或CGLIB(类级)实现代理对象生成 | 接口代理与类代理的性能差异 |
2.实现AOP机制(2)
知识点 | 核心内容 | 重点 |
AOP机制与后置处理器 | 分析AOP机制与Spring后置处理器的关联,并手动实现核心逻辑 | 动态代理与原生Bean的切换逻辑 |
SmartAnimal接口实现 | 定义SmartAnimalAble接口及SmartDog实现类,标注@Component | 接口方法注入容器的条件 |
切面类简化实现 | 创建SmartAnimalAspect切面类,暂未使用注解,包含前置通知(beginLog)和返回通知(showSuccessLog) | 切面方法与原生Spring注解的差异 |
后置处理器代理逻辑 | 在after方法中判断返回原生Bean或代理对象(当前仅针对SmartDog) | 注解解析与动态代理的灵活扩展 |
先死后活开发策略 | 优先固定代码实现核心流程,后续优化灵活性(如注解解析、表达式匹配) | 简化版与完整版的过渡逻辑 |
3.实现AOP机制(3)
知识点 | 核心内容 | 重点 |
后置处理器的作用 | 在Spring容器中处理bean的初始化后逻辑,支持AOP代理对象生成 | 执行时机(after方法)与前置处理器(before方法)的区别 |
动态代理实现AOP | 通过Proxy.newProxyInstance()生成代理对象,需传入ClassLoader、接口数组和InvocationHandler | JDK动态代理与CGLIB代理的适用场景差异 |
InvocationHandler核心逻辑 | 在invoke()方法中实现前置通知、目标方法调用、返回通知的链式调用 | 方法匹配逻辑(硬编码equals("getSum"))与注解式切面的灵活性对比 |
先死后活开发原则 | 硬编码smartDog作为测试用例,后续通过注解扩展 | 临时方案与最终解耦方案的过渡设计 |
切面方法执行流程 | 1. 前置通知(showBegin) 2. 目标方法反射调用(method.invoke) 3. 返回通知处理 | 反射调用参数(bin对象+args数组)的传递逻辑 |
注解驱动AOP雏形 | 提及通过注解(如@Before)动态识别需增强的方法 | 切点表达式解析与硬编码方法的优劣对比 |
4.实现AOP机制(4)
知识点 | 核心内容 | 重点 |
AOP代理机制实现 | 代理对象创建与返回逻辑,通过判断条件决定返回原生对象或代理对象 | if条件判断与return语句的执行顺序 |
代理对象测试验证 | 通过getSmartDog()获取代理对象并测试方法调用 | 代理对象类型转换(SmartAnimalAble)与方法调用验证 |
通知机制实现范围 | 当前仅对getSum方法实现前置和返回通知处理 | 未处理的方法(如getSub)不会触发通知 |
注解化改造方向 | 提及后续可通过@Before/@After等注解配合切面表达式实现灵活配置 | 当前"先死后活"方案与未来注解方案的对比 |
代理对象创建位置 | 在invoke方法外部完成代理对象创建并提前返回 | 大括号作用域与返回时机的控制 |
5.实现AOP机制(5)
知识点 | 核心内容 | 重点 |
AOP机制灵活性改进 | 通过注解和数据结构优化硬编码实现 | 注解与反射机制的结合使用 |
Spring原生AOP对比 | 通配符处理和切入表达式解析复杂度 | 原生Spring与简化实现的差异 |
注解开发实践 | 自定义@Aspect/@Before/@After注解 | 注解属性与切入表达式对应关系 |
框架底层原理 | 反射+容器+字符串处理的综合应用 | 基础语法与框架实现的衔接点 |
扩展开发思路 | Map数据结构与算法在AOP中的应用 | 业务逻辑与底层机制的平衡 |
6.实现AOP机制(6)
知识点 | 核心内容 | 重点 |
AOP切面编程实现 | 通过反射动态解析@Before和@AfterReturning注解,实现代理方法的调用链 | 注解值提取与反射调用的关联逻辑 |
反射机制应用 | 通过Class.getDeclaredMethods()遍历方法,结合getAnnotation()获取注解信息 | 方法名与注解值的动态绑定 |
注解解析流程 | 1. 获取切面类Class对象; 2. 遍历方法匹配注解; 3. 反射调用目标方法 | @Before的value表达式解析与执行时机 |
动态代理扩展 | 通过Map预存切面方法与目标方法的映射关系,实现灵活调用 | Map结构设计与代理逻辑耦合度 |
调试技巧 | 通过Debug演示反射调用链(如showBeginLog和showSuccessLog的执行顺序) | 反射调用时的异常处理与日志输出 |
7.梳理小结
知识点 | 核心内容 | 重点 |
Spring容器工作流程 | 扫描bin定义文件 → 封装BeanDefinition → 存入Map → 处理单例/多例实例化 | 单例与多例(prototype)的实例化时机差异 |
依赖注入机制 | 通过@Autowired在createBean时进行依赖匹配 | BeanDefinitionMap中的class对象反射处理 |
Bean后置处理器 | 在after方法中生成动态代理对象实现AOP | 代理对象invoke方法与通知类型的关联 |
IOC核心实现 | BeanDefinitionMap存储(name→BeanDefinition)结构 | 单例池与prototype动态创建的区别存储 |
动态代理实现AOP | 后置处理器生成代理对象拦截方法调用 | 前置/返回/异常/最终通知的切入时机 |
8.为什么需要JdbcTemplate
知识点 | 核心内容 | 重点 |
JDBC Template 引入背景 | Spring 框架操作数据库的需求,对比自研工具类 JdbcUtils 的局限性 | 自研工具类 vs. Spring 官方方案 的功能差异 |
JDBC Template 定义 | Spring 提供的数据库操作类,支持 CRUD 和批量操作 | 类(class)本质与 IOC 容器配置 关联 |
功能优势 | 灵活性(配置驱动)、场景适应性、批量操作支持 | 与自研工具类在扩展性、维护性上的对比 |
应用场景 | Spring 框架项目中替代原生 JDBC 或自研工具类 | 实际项目集成 的配置要点(需后续讲解) |
9.JdbcTemplate基本介绍
知识点 | 核心内容 | 重点 |
JDBC Template 概述 | Spring 提供的数据库访问技术,封装 JDBC 常用操作为模板方法 | 需引入相关 jar 包(如 org.springframework.jdbc.core) |
JDBC Template 构造器 | 1. 无参构造 2. 传入 DataSource 3. 支持懒初始化配置(lazyInit) | 数据源依赖:必须通过 DataSource 获取数据库连接 |
API 文档使用 | 通过 Spring 官方文档(docs 文件夹)搜索 JdbcTemplate 类,Ctrl+F 快速定位 | 方法数量庞大,需重点掌握高频核心方法 |
核心方法特点 | 提供大量数据库操作方法(如 CRUD、批量操作等),功能强大且高度封装 | 方法选择优先级:根据业务场景筛选常用方法 |
实际应用准备 | 需提前引入相关依赖包,确保包路径匹配(如 org.springframework.jdbc) | 依赖冲突风险:需检查现有 jar 包兼容性 |
10.JdbcTemplate-搭建环境
知识点 | 核心内容 | 重点 |
JDBC Template 基础配置 | 引入五个核心依赖包(c3p0数据源、MySQL驱动、spring-jdbc、spring-orm、spring-tx) | 依赖包作用混淆(如orm与tx功能差异) |
JDBC Template 核心类 | JdbcTemplate 类(1337行代码)实现 JdbcOperations 接口,支持注入Spring容器 | 类继承关系(JdbcAccessor 父类作用) |
数据库操作准备 | 创建 spring 库与 monster 表(含id、name、skill字段),初始化三条测试数据 | SQL脚本执行顺序(需逐条执行避免语法错误) |
API 方法范围 | 提供大量增删改查方法(如 query(), update()),但仅演示核心API | 方法选择优先级(高频API vs 边缘方法) |
事务管理支持 | 通过 spring-tx 包实现事务控制,与ORM操作集成 | 事务隔离级别配置(文中未明确说明) |
11.JdbcTemplate-配置Datasource
知识点 | 核心内容 | 重点 |
JDBC属性文件配置 | JDBC.properties文件包含数据库连接信息:用户名、密码、驱动类、URL | 属性键名可自定义(如JDBC.user或user) |
数据源对象配置 | 使用ComboPooledDataSource配置连接池,需注入4个关键属性 | 属性值通过${}语法从外部文件读取 |
Spring容器集成 | 通过context:property-placeholder引入外部属性文件 | 需注意XML命名空间配置 |
连接验证测试 | 通过getConnection()验证数据源有效性,返回的是代理连接对象 | 连接关闭异常处理需注意 |
对象获取方式 | 可通过接口类型(DataSource.class)获取Bean | 优于具体实现类获取方式 |
开发注意事项 | 数据库配置需与实际环境一致,IDEA无提示时可尝试重启 | URL格式必须完整准确 |
12.JdbcTemplate-添加数据
知识点 | 核心内容 | 重点 |
JDBC Template配置 | 配置全路径org.springframework.jdbc.core.JDBCTemplate,需关联dataSource属性 | dataSource属性与dataSource对象的区别 |
数据添加方式一 | 使用execute()方法直接执行完整SQL语句 | SQL注入风险(未使用参数化查询) |
数据添加方式二 | 使用update()方法配合问号占位符实现参数化查询 | 返回值含义(受影响记录数) |
对象获取方式 | 通过IOC容器按类型获取getBean(JDBCTemplate.class) | 调试技巧:断点查看容器内对象关系 |
SQL语句编写 | INSERT INTO monster VALUES与参数化INSERT INTO monster VALUES(?,?,?)对比 | 问号参数顺序绑定机制 |
13.JdbcTemplate-修改数据
知识点 | 核心内容 | 重点 |
JDBC Template数据修改 | 使用update方法执行SQL修改语句,需传入SQL语句和参数值 | 返回值含义:即使数据未实际变化也返回1(执行成功) |
SQL语句构造 | UPDATE语句结构:UPDATE table SET field=? WHERE id=? | 字段名必须与数据库严格匹配,否则报错 |
参数绑定 | 使用问号占位符,按顺序传入参数值 | 参数顺序必须与SQL中的问号位置一致 |
修改结果验证 | 通过affected返回值判断执行影响行数 | 特殊场景:新旧值相同时仍返回1 |
实战演示 | 修改monster表中id=300记录的scale字段为"美语句" | 需通过数据库客户端刷新验证实际修改结果 |
14.jdbctemplate-批量处理
知识点 | 核心内容 | 关键代码/操作 |
JDBC Template批量添加 | 使用batchUpdate方法实现批量数据插入 | jdbcTemplate.batchUpdate(sql, batchArgs) |
API使用技巧 | 三步法: 1.猜测API名称 2.准备参数 3.测试调整 | 通过batchUpdate方法演示参数组织过程 |
批量操作原理 | 返回int数组表示每条SQL影响记录数 | new Object[]{600,"老鼠精","偷吃粮食"} |
数据库连接管理 | 演示MySQL服务重启操作流程 | 服务管理面板操作演示 |
开发调试技巧 | 实时数据库验证操作结果 | SQLyog工具连接验证 |
15.jdbctemplate-查询后封装成对象
知识点 | 核心内容 | 重点 |
JDBC Template查询封装 | 使用queryForObject方法将查询结果自动封装到实体对象 | 字段名必须与实体类属性严格匹配(需使用别名解决字段映射问题) |
RowMapper接口应用 | 通过BeanPropertyRowMapper实现查询结果到JavaBean的自动映射 | 必须指定目标类的Class对象(反射机制要求) |
SQL语句优化 | SELECT查询应显式列出字段而非使用* | 字段别名设置技巧(monster_id AS id) |
API查找方法论 | 通过方法名前缀(如query/update)和接口实现类定位(Ctrl+Alt+B) | 反射机制在ORM中的底层应用 |
异常处理 | 类型未定义错误(Map class was not defined)解决方案 | 空值处理注意事项(未匹配字段返回null) |
16.jdbctemplate-查询后封装成对象集合
知识点 | 核心内容 | 重点 |
API调用方法 | 使用query方法查询并封装多个结果对象,返回List<Monster>集合 | queryForObject(单结果)与query(多结果)的区别 |
SQL参数化查询 | 通过?占位符动态传入参数(如ID > ?),避免SQL拼接风险 | 参数绑定与直接拼接SQL的安全性差异 |
RowMapper复用 | 相同实体类(Monster)的映射逻辑可直接复用RowMapper实现 | 不同查询结果复用同一映射器的前提条件 |
集合结果处理 | 遍历List<Monster>输出查询结果,适用于非唯一性条件查询 | 单结果(Optional)与多结果(List)的适用场景对比 |
JDBC Template核心方法 | query(String sql, RowMapper<T> rowMapper, @Nullable Object... args)的参数结构 | 方法重载(带参数/不带参数)的选择依据 |