不动源码,怎么改框架行为
改第三方框架的行为,硬改源码是下策——升级就丢。Spring 的答案是扩展点(钩子):框架在关键流程预留接口,你实现它,框架在合适的时机回调你。Spring 全家桶的扩展点上百个,常用的十来个,按容器、配置、Web 三层盘点。
容器层:改定义与改对象
BeanFactoryPostProcessor:在 Bean 还没实例化时介入,操作的是 Bean 定义——最著名的例子是 PropertySourcesPlaceholderConfigurer,把 @Value 里的占位符替换成真实值的就是它。BeanPostProcessor:实例化之后介入,改对象、包代理——第 4 篇讲过的四大金刚,事务和 AOP 的底层支撑,@PostConstruct 的执行也是它在调度。这一层是 Spring 内部魔法的地基,前面几篇已经反复打过照面。
配置层:改环境与改配置源
EnvironmentPostProcessor:在配置文件加载进环境后、容器刷新前介入——数据库密码加密存储,在这里解密后塞回环境;Boot 没有直接扫描它,需要注册进 META-INF/spring.factories。PropertySource:自定义配置源,把配置从数据库、配置中心、甚至 Redis 里读进来,实现一个 resolve 方法就能无缝接入 @Value 和 @ConfigurationProperties 体系。配置层的钩子用好了,配置管理的路子一下子宽了。
Web 层:日常使用率最高的一层
HandlerInterceptor:拦截请求做登录校验、权限检查、链路追踪埋点;Filter:更外层,处理编码、跨域、请求日志;Converter 与 Formatter:参数转换,前端传来的日期字符串就是在这里变成本地日期(LocalDate);@ControllerAdvice:全局异常处理与统一响应包装,使用率最高,几乎每个项目都有一个:
@RestControllerAdvice
public class GlobalExceptionHandler {
// 业务异常:拦截后转成统一响应体
@ExceptionHandler(BizException.class)
public Map<String, Object> handleBiz(BizException e) {
Map<String, Object> result = new HashMap<>();
result.put("code", e.getCode());
result.put("msg", e.getMessage());
return result;
}
// 兜底异常:吞掉堆栈细节,避免泄漏内部信息
@ExceptionHandler(Exception.class)
public Map<String, Object> handleOther(Exception e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 500);
result.put("msg", "系统开小差了,请稍后再试");
return result;
}
}用钩子记住一个原则:选对层次再动手——改 Bean 用 BPP、改配置用 EnvironmentPostProcessor、改请求用 Interceptor,跨层乱用会把简单问题搞复杂;多个同类钩子之间用 @Order 排顺序,别让执行顺序变成玄学。
下一篇收官复盘:把十八篇串成一张 Spring 作战地图,附排查手册与源码阅读路线。
评论 (0)