如何注入Supplier类型的Bean?注入时出现Class has no fields错误如何解决
问题原因
- Spring 对
Supplier类型的特殊解析逻辑:Spring 4.3及以上版本默认支持Supplier作为依赖注入的包装类型,会自动解析Supplier<T>对应的T类型的Bean,而非直接注入Supplier实例本身,导致你注册的Supplier<Set<String>>Bean没有被正确匹配到注入点。 - Lambda实现的
Supplier代理失败:你通过lambda表达式返回的Supplier是JDK动态生成的合成类,该类被final修饰且无公开构造方法,当配置类默认开启proxyBeanMethods = true时,Spring会尝试对@Bean返回的实例做CGLIB代理,lambda生成的类无法被代理,触发"Class has no fields"报错。
解决方法
方法1:给Supplier Bean指定名称,注入时按名称匹配
给配置类的Supplier Bean添加自定义Bean名:@Bean("stringSetSupplier") public Supplier<Set<String>> set() { return () -> Sets.newHashSet("100"); }类A中注入时指定对应Bean名:
@Inject @Named("stringSetSupplier") private Supplier<Set<String>> set;这种方式可以跳过Spring的
Supplier自动解包逻辑,直接按名称匹配到你注册的Supplier实例。方法2:使用具名类实现Supplier,避免lambda代理问题
定义一个静态类实现Supplier接口:public static class StringSetSupplier implements Supplier<Set<String>> { @Override public Set<String> get() { return Sets.newHashSet("100"); } }配置类中返回该类的实例:
@Bean public Supplier<Set<String>> set() { return new StringSetSupplier(); }具名类可被Spring正常代理,不会触发合成类相关的报错。
方法3:关闭配置类的Bean方法代理
如果你不需要配置类的Bean方法代理能力,直接修改配置类注解关闭代理:@Configuration(proxyBeanMethods = false) @Import({someClass.class}) public class UnitTestConfig { // 原有配置保持不变 }关闭代理后Spring不会再尝试对@Bean返回的实例做CGLIB增强,规避lambda类无法代理的问题。
内容的提问来源于stack exchange,提问作者Denise
相关产品推荐
相关产品推荐

