为什么BeanPostProcessor的postProcessAfterInitialization方法未被调用
问题排查及解决方案
核心问题排查点
- 首先修正代码语法错误:你贴出的
postProcessAfterInitialization方法最后一行return bean缺少分号,先修正该问题保证类可以正常编译加载。 - 补全
Ordered接口实现:你当前实现了Ordered接口但没有重写getOrder()方法,Spring默认会给未指定优先级的BeanPostProcessor分配最低优先级,很容易出现Controller bean被其他高优先级BPP提前初始化完成,导致你的postProcessAfterInitialization方法漏触发,添加如下方法即可:
@Override public int getOrder() { // 设为最高优先级,保证优先执行你的BPP逻辑 return Ordered.HIGHEST_PRECEDENCE; }
- 检查上下文匹配问题:Spring MVC架构中
@RestController默认归属DispatcherServlet的子上下文管理,如果你的UTF8DecodeQueryAnnotationBeanPostProcessor被扫描到了根Spring上下文,就会出现只能处理根上下文bean的before方法、无法处理子上下文Controller的after方法的问题,需要保证BPP和Controller在同一个Spring上下文的扫描范围内。
代理逻辑优化
就算postProcessAfterInitialization成功触发,你当前直接用Cglib Enhancer.create生成代理的逻辑存在缺陷:如果Controller已经被Spring的其他逻辑生成过代理(比如加了@Transactional、权限校验切面等),你直接新建的代理会丢失原bean的Spring依赖注入属性、上下文关联配置,建议改用Spring自带的ProxyFactory生成代理:
ProxyFactory proxyFactory = new ProxyFactory(bean); proxyFactory.addAdvice((MethodInterceptor) invocation -> { Method method = invocation.getMethod(); Object[] args = invocation.getArguments(); if(method.isAnnotationPresent(UTF8DecodeQuery.class)) { // 这里处理query参数的解码逻辑,修改args数组对应位置的值即可 } return invocation.proceed(); }); return proxyFactory.getProxy();
更适配的替代实现方案
如果你只是为了学习,上述BPP方案可以正常运行,如果想找更适配请求参数预处理的实现,可以用Spring MVC原生的HandlerInterceptor,不需要自己写代理逻辑,代码更简洁:
- 实现
HandlerInterceptor接口,重写preHandle方法 - 从
HttpServletRequest中获取query参数,完成UTF8解码后,修改request的参数映射 - 把拦截器注册到Spring MVC的拦截器链中,指定匹配的接口路径即可
内容的提问来源于stack exchange,提问作者Eduard Balakh
相关产品推荐
相关产品推荐

