
1、错误信息线上代码在发布或者业务高峰期时偶发报错报错信息如下org.springframework.beans.factory.BeanCreationException: Error creating bean with name processingTaskContext defined in URL [jar:file:/app/store-depot-consumer.jar!/BOOT-INF/classes!/com/pupu/consumer/store/depot/consumer/processing/ProcessingTaskContext.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Could not access method: class org.springframework.util.ReflectionUtils cannot access a member of class com.pupu.consumer.store.depot.consumer.processing.ProcessingTaskContext with package access at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.$sw$original$doCreateBean$5pu2ek3(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.$sw$original$doCreateBean$5pu2ek3$accessor$$sw$pkpdnj2(AbstractAutowireCapableBeanFactory.java) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]2、排查的思路一开始以为是成员变量的可见范围导致注入失败将含有ApolloJsonValue的成员变量由private改成了protected,发布上线后还是会存在偶发报错后续借助ai代码溯源发现apollo-client 1.25.0 的中有段代码boolean accessible field.isAccessible(); field.setAccessible(true); ReflectionUtils.setField(field, bean, ...); field.setAccessible(accessible);当存在多线程编发的时候会出现以下场景环节事实Bean 作用域ProcessingTaskContext 是 Scope(PROTOTYPE)每条 Kafka 消息 getBean() 新建实例多线程并发Field 共享Spring 4.3 的 ReflectionUtils.doWithFields 用 declaredFieldsCache 缓存 Field[]所有线程共享同一个 Field 实例Apollo 注入模式apollo-client 1.25.0 的 processField保存 isAccessible → setAccessible(true) → 注入 → 恢复原值已通过反编译 sources jar 双重验证竞态时序线程 A 刚 setAccessible(true) 准备注入 → 线程 B 注入完毕把状态恢复为 false → 线程 A 的 field.set() 在 overridefalse 下执行访问检查 → 调用方 org.springframework.util.ReflectionUtils 与该类不同包 → 除 public 外的任何可见级别都会抛异常3、解决办法方案将两个 ApolloJsonValue 字段改为 publicpublic 成员不依赖 setAccessible竞态下也安全并加了注释防止后续被顺手改回去注意事项项目中其他所有 ApolloJsonValue 都在单例 Bean 中启动时单线程创建一次无竞态只有这一个 prototype Bean 受影响。同时已更正之前记录的错误经验。风险提示与建议验证 (Risks Verification)功能无风险仅放宽可见性语义不变这两个字段本就只在类内部读取Apollo 热更新路径SpringValue.injectField在 public 字段下同样安全。建议验证发布后观察 processingTaskContext 的 BeanCreationException 告警是否归零。由于原错误是偶发的取决于并发窗口建议至少观察一个完整高峰期或压测并发消费加工消息来确认。潜在残留风险竞态本身在 apollo-client 1.25.0 里依然存在只是 public 字段让它变得无害。如果未来在 prototype Bean 中新增 ApolloJsonValue 字段必须用 public注释和记忆库都已标注。长期更彻底的方案是推动 apollo-client 升级去掉 setAccessible 的保存-恢复模式。