@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

我正在将 spring 从 4.3.3 升级到 5.2.7,我遇到了这个异常:

异常:

Related cause: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MyBean' defined in com.test: Unsatisfied dependency expressed through method 'MyBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 

代码:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@SuppressWarnings({ "unchecked" })
public MyBean MyBean(String url,
        String user, String password, String id) {
    return MyBean(url, user, password, id,
            new HashMap<String, String>(),false); 
}

PS 1: I'm using context.getBean with args to init my bean

PS 2: I'm facing this problem at the startup of the application even though im not using the bean at the startup ( I'm using @Scope("prototype") to init the bean whenever it's called)

PS 3: I didn't have the problem with spring 4.3.3

这可能是由于 Spring 5.x.x 版本 -

的未解决问题

https://github.com/spring-projects/spring-framework/issues/21498

它讨论了特定于 5.x.x 版本的问题。

Since Spring 5.0 a @Bean can return null and the effect is to leave the bean definition in the registry, but make the value not autowirable. However, if there is another bean of the same type that is not null, it does not become autowirable. Probably it should? The exception from Spring doesn't mention the existence of either bean (the null or the not null one)

尝试将字段标记为可选,这样启动时就不会失败。

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@SuppressWarnings({ "unchecked" })
public Optional<MyBean> MyBean(Optional<String> url,
        Optional<String> user, Optional<String> password, Optional<String> id) {
    if(url.isEmpty() && user.isEmpty() && password.isEmpty() && id.isEmpty()) {
     return Optional.empty();
    } 
    return Optional.of(new MyBean(url, user, password, id,
            new HashMap<String, String>(),false)); 
}

更新 1

我认为这是更简单的解决方案。 Spring 5.0 添加了 Nullable 注释,可能他们只为这种情况添加了这个注释。

API 文档 Link - https://docs.spring.io/spring/docs/5.0.0.RC1_to_5.0.0.RC2/Spring%20Framework%205.0.0.RC2/org/springframework/lang/Nullable.html

A common Spring annotation to declare that the annotated parameter or return value could be null under some circumstances.

所以只需要将参数和 return 类型标记为 Nullable。

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  @SuppressWarnings({ "unchecked" })
  public @Nullable MyBean myBean(@Nullable String url,
                                 @Nullable String user, @Nullable String password, @Nullable String id) {
    if(url == null && user == null && password == null && id == null) {
      return null;
    }
    return new MyBean(url, user, password, id,
            new HashMap<String, String>(),false);
  }