学习日记-spring-day40-7.3

发布于:2025-07-04 ⋅ 阅读:(15) ⋅ 点赞:(0)

知识点:

1.自动装配@Resource(3)

知识点

核心内容

重点

@Autowired与@Resource注入规则

默认注入逻辑:未指定参数时,@Resource优先按属性名匹配(by name),失败后按类型匹配(by type);两者均失败则报错

名称匹配优先级:属性名需与容器中Bean的ID完全一致

多实例场景下的依赖注入

容器中存在多个同类型Bean时:

- 仅当属性名与某一Bean ID匹配时成功;

- 类型匹配必然失败(需唯一性)

典型错误场景:存在3个UserService实例时,未明确指定名称的注入

注解使用规范建议

1. 优先使用@Resource;

2. 属性名需符合驼峰命名规范(如userService);

3. 泛型依赖等特殊场景仍需@Autowired

版本差异:@Autowired未被废弃但官方推荐替换

验证实验设计

通过修改Bean ID(如userService200)与属性名对比: - 同名匹配成功案例; - 无匹配时的类型检查报错

调试技巧:输出Bean哈希值验证注入实例

面试高频考点

1. 两种注解的匹配顺序差异;

2. 多实例冲突解决方案;

3. 官方推荐注解的演变

易错点:认为@Resource会智能合并名称与类型策略

2.自动装配小结

知识点

核心内容

重点

自动装配的注意事项

当待装配类型在IOC容器中有多个实例时,使用属性名作为ID值进行查找

装配失败会抛出异常

@Autowired与@Qualifier配合使用

通过@Autowired+@Qualifier("指定ID")实现精确装配

需要同时使用两个注解

@Resource注解使用

通过@Resource(name="指定ID")单注解实现装配

优先按name匹配,其次按类型

装配规则对比

@Autowired:先类型后名称

@Resource:先名称后类型

两种注解的匹配顺序差异

最佳实践建议

推荐使用@Resource+规范属性名

保证命名规范性可避免混淆

3.泛型依赖注入(1)

知识点

核心内容

重点

泛型依赖注入

Spring提供的基于泛型的自动装配机制,通过父类泛型标识实现子类依赖注入

泛型类型传递父类自动装配逻辑的关联性

BaseDAO设计模式

支持泛型的基类DAO,子类通过继承并指定泛型类型实现具体操作

泛型类继承时的类型确定时机(创建对象/继承时)

BaseService与DAO关联

通过泛型依赖注入自动将BookDAO装配到BookService,避免重复声明属性

父类泛型参数如何映射到子类依赖关系

泛型基础回顾

自定义泛型类、泛型类型擦除等Java基础概念

泛型类与普通类的实例化差异

实际应用场景

继承关系复杂的项目(如家居购项目)中简化依赖配置

传统装配方式与泛型注入的代码量对比

4.泛型依赖注入(2)

知识点

核心内容

重点

泛型依赖注入机制

通过泛型传递实现自动装配(如BaseService<T>注入BaseDao<T>子类)

泛型类型推导与普通@Autowired的区别

Spring注解应用

@Repository标记DAO层、@Service标记业务层

@Autowired在泛型场景下的强制使用

IOC容器调试

通过断点查看singletonObjects验证依赖关系

动态绑定机制与运行时类型识别

分层架构设计

BaseDao→BookDao/PhoneDao,BaseService→BookService/PhoneService

抽象类与泛型的联合应用

配置文件管理

多配置文件拆分(beans06.xml→beans07.xml)

包扫描路径与注解扫描范围

5.AOP文档说明

知识点

核心内容

重点

AOP(切面编程)

通过动态代理机制实现功能解耦,核心支撑技术包括反射和动态绑定

动态代理的实现原理与反射机制的关系

动态代理

支撑AOP的核心技术,涉及反射和动态绑定

动态代理与静态代理的区别及适用场景

Spring AOP文档

官方文档位置:reference中的aspect oriented programming with spring章节及org.springframework.aop包API

API查找路径与实际开发中的高频使用类

学习难点

理解底层机制(动态代理、反射)及实际应用场景

切面编程的抽象概念与具体代码实现的对应关系

6.动态代理需求说明

知识点

核心内容

重点

动态代理

AOP的核心支撑技术,需通过案例理解其实现逻辑

代理模式与原生调用的区别

InvocationHandler接口的作用

传统方案实现

直接在Car/Ship的run()方法中硬编码"开始/停止"逻辑

代码重复问题

违反开闭原则

动态代理优势

通过代理类统一处理公共逻辑(如"交通工具开始/停止运行")

反射调用的性能损耗

接口代理的限制

案例需求

对Vehicle接口的run()方法增强:

1. 统一前置/后置输出

2. 保留子类特有逻辑

增强逻辑与业务逻辑的分离

JDK动态代理与CGLIB的区别

重点

通过对比传统方案与动态代理方案突出解耦价值

AOP底层原理的关联性

Spring AOP的代理选择策略

7.传统方法解决需求

知识点

核心内容

重点

动态代理概念

通过接口编程实现方法调用的统一控制,解决代码冗余问题

动态绑定机制与接口多态性

传统实现方式

直接在实现类中硬编码前后置逻辑(Car/Ship类)

接口引用指向实现类对象的OOP特性

代码冗余问题

相同的前后置日志出现在所有实现类中

维护成本与统一管理难点

动态代理优势

统一管理方法调用的前后置操作(日志/权限/事务等)

AOP编程思想的实现基础

Vehicle接口示例

定义run()抽象方法,Car/Ship分别实现

编译类型与运行类型的动态绑定

开发场景应用

权限校验/安全验证/事务管理等横切关注点

代理模式与装饰器模式区别

教学演示步骤

1. 创建接口 2. 编写实现类 3. 暴露冗余问题 4. 引入代理方案

测试用例中接口引用的多态应用

8.动态代理解决问题(1)

知识点

核心内容

重点

动态代理实现原理

通过Proxy.newProxyInstance()生成代理对象,底层基于反射机制

接口必须保持不变,代理对象需实现相同接口

代理对象创建流程

1. 获取类加载器

2. 获取接口信息

3. 实现InvocationHandler处理调用逻辑

InvocationHandler匿名内部类实现是关键步骤

InvocationHandler作用

通过invoke()方法拦截目标方法调用,可插入前置/后置逻辑(如日志)

method.invoke(target,args)反射调用原始方法易遗漏

反射调用与动态代理关系

动态代理通过反射调用目标方法(method.invoke(target,args))

需确保目标类实现接口,否则无法代理

匿名内部类应用场景

快速实现InvocationHandler接口,避免单独创建类文件

匿名类中访问外部变量需final修饰(JDK8+隐式支持)

代理模式优势

解耦核心逻辑与横切关注点(如日志、事务)

动态代理 vs 静态代理(需手动编写代理类)

9.动态代理解决问题(2)

知识点

核心内容

重点

动态代理(Proxy)实现原理

通过Proxy.newProxyInstance创建代理对象,传入目标对象和InvocationHandler,代理对象执行方法时会触发invoke方法

编译类型与运行类型的区别:代理对象编译类型仍是接口,但运行类型变为$Proxy0等动态生成的代理类

代理对象执行流程

调用代理对象方法时,先执行InvocationHandler.invoke,再通过反射调用目标对象方法(如ship.run())

易混淆点:直接调用目标对象方法不会触发代理逻辑,必须通过代理对象调用

类型判定关键代码

通过proxy.getClass()获取代理对象的运行类型,对比编译类型(接口)与运行类型($Proxy0)

重点验证方法:断点调试观察getClass()结果,结合反射验证方法调用链

代理模式应用场景

演示通过代理对象增强原始方法(如添加“交通工具开始/停止运行”日志)

典型场景:日志记录、权限校验、事务管理(AOP底层实现)

调试技巧

通过断点+表达式估算(proxy.getClass())观察运行类型,对比直接调用与代理调用的堆栈差异

易错点:未正确传入InvocationHandler或目标对象导致代理失效

10.动态代理机制Debug(1)

知识点

核心内容

重点

动态代理机制

通过Proxy类创建代理对象,代理对象的运行类型决定方法调用路径

运行类型≠编译类型时方法调用路径变化

反射调用流程

通过Method.invoke()实现方法动态调用,最终执行被代理对象的方法

invoke参数传递机制(target对象+arguments数组)

调试技巧

使用step into/step over跟踪代理调用链,需关闭"step into"过滤设置

IDE调试配置差异导致无法进入JDK源码的问题

动态绑定验证

通过修改被代理对象(Ship→Car)验证运行时的动态绑定效果

代理对象不变情况下仅target对象变化即可改变执行逻辑

void方法处理

无返回值方法执行后result为null的反射特性

基本类型返回值与对象返回值的处理差异

11.动态代理机制Debug(2)

知识点

核心内容

重点

动态代理机制

target对象动态变化:传入不同对象执行对应方法

方法动态调用:通过代理对象调用的方法会动态传入

代理对象与实际执行对象的映射关系

反射机制在动态代理中的应用

方法调用过程

包含参数传递、返回值处理的完整调用链演示

关键步骤

1. 参数类型转换(int→Integer)

2. 方法反射调用

3. 返回值多层传递

Debug技巧:

- 需要两次step into进入核心逻辑

- 参数传递的隐式类型转换

动态性体现

1. 被代理对象可替换(Car/Ship)

2. 调用方法可扩展(run/fly)

3. 参数动态传递(高度参数)

代理接口与实现类的松耦合关系

调试技巧

关键断点

- 方法调用入口

- 参数转换节点

- 返回值传递路径

特殊操作

- step out后需立即step into

Integer.valueOf的自动装箱过程

反射调用时的参数封装

框架应用

MyBatis等框架底层原理

- 动态代理实现接口映射

- 方法拦截与增强

动态代理在AOP中的应用场景