使用Spring ReflectionUtils设置泛型类字段值异常求助
问题分析与解决方案
问题根源
你遇到的两个bean的type字段最终都变为B.class,核心原因大概率是beanA和beanB是同一个实例:
Spring默认的bean作用域是单例,如果你的bean配置没有为不同泛型类型创建独立实例,那么注入到MyService的beanA和beanB其实是同一个GenericServiceImpl对象。此时第二次设置B.class会覆盖第一次设置的A.class,导致两个引用指向的对象type值一致。
其次,你使用的字段过滤条件field.getType() == Class.class不够严谨:虽然当前GenericServiceImpl只有type一个Class类型字段,但如果后续新增同类型字段,会误操作其他字段。
解决方案
方案1:确保bean实例独立(优先)
在Spring配置类中为不同泛型类型创建独立的bean实例,避免单例复用:
@Configuration public class GenericServiceConfig { @Bean public GenericService<A> beanA() { return new GenericServiceImpl<>(); } @Bean public GenericService<B> beanB() { return new GenericServiceImpl<>(); } }
方案2:修正ReflectionUtils的使用逻辑
替换doWithFields为更精准的findField,直接定位type字段,避免不必要的字段遍历:
@PostConstruct public void init() { // 设置beanA的type字段 Field typeField = ReflectionUtils.findField(beanA.getClass(), "type"); if (typeField != null) { ReflectionUtils.makeAccessible(typeField); ReflectionUtils.setField(typeField, beanA, A.class); } // 设置beanB的type字段 typeField = ReflectionUtils.findField(beanB.getClass(), "type"); if (typeField != null) { ReflectionUtils.makeAccessible(typeField); ReflectionUtils.setField(typeField, beanB, B.class); } }
方案3:构造时直接初始化(最优实践)
利用GenericServiceImpl的带参构造函数,在创建bean时直接传入泛型类型,完全避免反射操作:
@Configuration public class GenericServiceConfig { @Bean public GenericService<A> beanA() { return new GenericServiceImpl<>(A.class); } @Bean public GenericService<B> beanB() { return new GenericServiceImpl<>(B.class); } }
这种方式符合Java初始化规范,无需依赖反射,代码更安全、可读性更强。
内容的提问来源于stack exchange,提问作者Mohamed Aoutir
相关产品推荐
相关产品推荐

