创建@Bean注释bean时,Spring @Required属性



我正在开发一个Spring Boot应用程序,并尝试使用基于Java注释的bean创建(使用@Configuration和@Bean),而不是熟悉的旧的基于xml的bean创建。但我很困惑。如果我尝试在XML中创建bean,但未能设置@Required属性,则在创建应用程序上下文时将获得BeanInitializationException。到目前为止,在我对基于注释的bean创建的试验中,情况似乎并非如此。

例如:

public class MyClass {
    ...
    @Required
    public void setSomeProp(String val){
    }
}

然后在Spring XML中:

<bean class="MyClass"/>

这将在应用程序启动期间爆炸(并且IntelliJ标记它),因为所需的属性没有设置。但这似乎并非如此:

@Configuration
public class MyConfig {
    @Bean
    public MyClass myClass() {
        return new MyClass();
    }
}

即使没有设置所需的属性,这个应用程序也可以正常启动。我一定是遗漏了什么,因为这似乎是Spring的一个非常关键的特性。

我做了一些调查&调试时发现bean定义被标记为跳过检查@Required字段的设置。在Spring类'RequiredAnnotationBeanPostProcessor'中,布尔方法'shouldSkip()'对于以这种方式创建的bean返回true。当我使用调试器强制该方法返回false bean创建时,确实出现了预期的异常。

鉴于我正在制作一个非常基本的Spring Boot应用程序,我倾向于(正如Zergleb建议的)将此作为bug提交。

更新2 进一步的调试表明,即使设置了字段,强制检查仍然会抛出相同的异常,就好像没有设置一样。所以也许dunni是正确的,并且没有办法使用@Bean表示法。

正如你所说,我也无法得到@Required按预期运行,这可能是一个bug,需要报告。我还有其他一些对我有用的建议。

用@Configuration注释的类

//With the bean set up as usual These all worked
@Bean
public MyClass myClass() {
    return new MyClass();
}

当你注释了@Component类,并使用组件扫描加载时,效果如预期。(组件扫描部分很重要,你要么需要你的@Configuration类有@ComponentScan,要么删除@Configuration并用@SpringBootApplication代替,这将启用组件扫描,而无需使用@Bean configs连接它们)

@Component // Added this
public class MyClass {
    ...
    @Required //Failed as expected
    public void setSomeProp(String val){
    }
}

使用@Autowired(required=true)//BeanCreationException失败//没有类型为[java.lang. lang]的合格bean。找到依赖项

//No more @Component
public class MyClass {
    ...
    @Autowired(required=true) //Fails
    public void setSomeProp(String val){
    }
}

@Autowired required=false//不崩溃

public class MyClass {
    ...
    @Autowired(required=false) //Simply never gets called if missing
    public void setSomeProp(String val){
    }
}

@Value//如果test。属性丢失//无法解析占位符的测试。${test.property}

public class MyClass {
    @Value("${test.property}")
    String someProp;
    //This getter is not neccesary neither is a setter
    public String getSomeProp() {
        return this.someProp;
    }
}

@Value与默认值//不会崩溃//当getSomeProp被调用时,它返回"我的默认值"(除非你有测试。property=应用程序中的任何内容。然后返回"Anything"

public class MyClass {
    @Value("${test.property:My Default Value}")
    String someProp;
    //This getter is not neccesary neither is a setter
    public String getSomeProp() {
        return this.someProp; //Returns "My Default Value"
    }
}

在你的@Configuration文件中,如果找不到任何东西来填充myClass方法中的String someProp,也会失败

@Bean
public MyClass myClass(String someProp) { //Fails being unable to populate this arg
    MyClass myObj = new MyClass();
    myObj.setSomeProp(someProp);
    return ;
}

当然这不起作用,因为您自己创建了MyClass的对象(new MyClass()),因此注释不会被计算。如果使用@Bean方法创建bean,容器将只确保所有依赖项都在那里(方法参数),并且bean作用域被遵守,这意味着如果它是单例bean,则每个应用程序上下文只创建一个bean。bean/对象本身的创建完全是开发人员的责任。

等价于xml <bean>标记的是用@Component注释类,其中bean完全由容器创建,因此注释被求值。

正如所说的,当您拥有自己的@Configuration类并在其中单独创建bean时,@Required并不适用于此。

如果你已经有了一个@Component,让Spring Boot做组件扫描,然后在所需的setter属性中添加@Autowired,它就会正常工作。

在网上找到这个链接- https://www.boraji.com/spring-required-annotation-example

例如:

我有一个名为Employee的组件,它有Id和Name。

@Component
public class Employee {
  int id;
  String name;
  public int getId() {
    return id;
  }
  @Autowired
  @Required
  public void setId(int id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }

}

我有一个名为AppConfig.java的配置类

@Configuration
public class AppConfig {
  @Bean
  public int getId() {
    return 1;
  }

}

所以现在我们看到,组件Employee需要一个Id属性在启动时绑定,所以我写了一个Integer类型的bean方法,它将在运行时自动连接。如果你不写一个Integer类型的bean,它将导致一个BeanCreationException。

这是我的主类文件。

@SpringBootApplication
public class SingletonApplication {
  public static void main(String[] args) {
    ApplicationContext ctx = 
       SpringApplication.run(SingletonApplication.class, args);
    Employee emp = (Employee)ctx.getBean(Employee.class);
    System.out.println(emp.getId());
  }
}

相关内容

  • 没有找到相关文章

最新更新