我正在开发一个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类&#39; RequiredAnnotationBeanPostProcessor&#39;布尔方法&#39; shouldSkip()&#39;对于以这种方式创建的bean,它返回true。当我使用调试器强制该方法返回false bean时,确实爆炸了预期的异常。
看到我正在制作一个非常基本的Spring Boot应用程序,我倾向于(正如Zergleb建议的那样)将其作为错误提交。
更新2 一些进一步的调试显示,即使字段设置强制检查仍然会抛出相同的异常,就好像它没有被设置。所以也许dunni是正确的,并且没有办法使用@Bean表示法。
答案 0 :(得分:1)
正如你所说,我也无法让@Required按预期运行,这可能是一个错误,需要报告。我还有其他一些对我有用的建议。
使用@Configuration
注释的类//With the bean set up as usual These all worked
@Bean
public MyClass myClass() {
return new MyClass();
}
当您注释类@Component并使用组件扫描加载按预期工作时。(组件扫描部分非常重要,您需要@Configuration类来使用@ComponentScan或者删除@Configuration并替换为@SpringBootApplication和this将启用扫描组件而无需使用@Bean配置连接它们
@Component // Added this
public class MyClass {
...
@Required //Failed as expected
public void setSomeProp(String val){
}
}
使用@Autowired(required = true)//使用BeanCreationException失败//没有为依赖项找到[java.lang.String]类型的限定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.property则无效//无法解析占位符&#39; test.property&#39;在字符串值&#34; $ {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时,它返回&#34;我的默认值&#34;(除非你的test.property = application.properties文件中的任何内容然后返回& #34;任何&#34;
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"
}
}
如果在myClass方法中找不到任何填充字符串someProp的话,那么@Configuration文件内部也会失败
@Bean
public MyClass myClass(String someProp) { //Fails being unable to populate this arg
MyClass myObj = new MyClass();
myObj.setSomeProp(someProp);
return ;
}
答案 1 :(得分:0)
如果当然这不起作用,因为你自己创建了MyClass的对象(new MyClass()),因此不会评估注释。如果使用@Bean
方法创建一个bean,容器只会确保所有依赖项都存在(方法参数)并且遵守bean范围,这意味着它只是一个单独的bean,只有每个应用程序上下文创建一个bean。 bean /对象本身的创建完全由开发人员负责。
xml <bean>
标记的等价物用@Component
注释类,其中bean完全由容器创建,因此评估注释。
答案 2 :(得分:0)
可以这么说,当您拥有自己的@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());
}
}