我有ServiceImpl,如下所示:
@Service
@RequiredArgsConstructor
public class ServiceAImpl implements ServiceA {
private final String fieldA;
@Override
public boolean isFieldA(String text){
return fieldA.equals(text);
}
我想在application.yml的Application.java中为fieldA注入一个字段值,如下所示:
@EnableSwagger2
@SpringBootApplication
public class Application {
@Value("${fieldA}")
private String fieldA;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ServiceA serviceA() {
return new ServiceAImpl(fieldA);
}
但是在运行SpringBoot应用程序时收到以下错误:
使用名称' serviceAImpl'创建bean时出错在URLNo限定bean中定义的类型' java.lang.String'可用:预计至少有1个豆有资格作为autowire候选者。依赖注释:{}
你有解决方法吗?
答案 0 :(得分:2)
您使用@Service
为您的班级注释,并将其手动定义为带有@Bean
注释的bean。我认为第二种是你计划使用它的方式。
@Service
注释将使该类被Spring的组件扫描拾取并另外创建它的实例。
当然它会尝试解析参数,并在尝试查找匹配的" bean时失败。对于String字段,因为没有简单的String bean(并且不应该:)。
删除@Service
注释,一切都应按预期工作。
答案 1 :(得分:1)
您正在使用两种bean声明机制:
@Service
@Bean
这意味着您的服务将被创建两次。使用@Bean
定义的那个正常工作,因为它使用@Value
注释在您的服务中注入适当的值。
但是,由@Service
创建的服务并不知道@Value
注释,并会尝试找到String
类型的任何bean,它可以“{1}}找到,因此它会抛出您正在看到的异常。
现在,解决方案是选择其中一个。如果您想保留@Bean
配置,则应从@Service
删除ServiceAImpl
注释,这样做会有所帮助。
或者,如果你想保留@Service
注释,你应该删除@Bean
声明,你应该编写自己的构造函数而不是依赖Lombok,因为这允许你使用{{ 1}}构造函数中的注释:
@Value
答案 2 :(得分:1)
试试这个
@EnableSwagger2
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
和这个
@Service
您不应该将@Bean
和const testData = {
groups: [
{
title: 'Current Year',
items: [
{title: 'All', value: 'XXXX'},
{title: 'Month', value: 'XXXX'},
{title: 'Days', value: 'XXXX'}
]
},
{
title: 'Next Year',
items: [
{title: 'All', value: 'XXXX'},
{title: 'Month', value: 'XXXX'},
{title: 'Days', value: 'XXXX'}
]
}
]
};
用于同一个类!
答案 3 :(得分:1)
春天并不那么聪明:)
你应该注释你的bean:
@RequiredArgsConstructor
public class ServiceAImpl {
@Value("${fieldA}")
private final String something;
...
但我不确定它是否适用于@RequiredFieldsConstructor
,您可以更简单地记下使用@Autowired
注释的构造函数并使用@Value
注释String
参数:
@Autowired
public ServiceAImpl(@Value("${aProp}") String string) {
答案 4 :(得分:0)
如果要在Java配置文件中将ServiceAImpl
声明为Spring bean,则应从类声明中删除@Service
注释。这些注释并不能很好地协同工作。
<强> ServiceAImpl.java 强>
import org.springframework.beans.factory.annotation.Autowired;
public class ServiceAImpl implements ServiceA {
private final String fieldA;
@Autowired
public ServiceAImpl(String fieldA) {
this.fieldA = fieldA;
}
@Override
public boolean isFieldA(String text) {
return fieldA.equals(text);
}
}
<强> Application.java 强>
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
@Value("${fieldA}")
private String fieldA;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ServiceA serviceA() {
return new ServiceAImpl(fieldA);
}
}
您的 application.properties
fieldA=value
答案 5 :(得分:0)
The below implementation works well for me. You have two issues, first you have to choose between @Service and @Bean and the other issue I've seen in your code was the @Value annotation, you have to use only to inject a value from the properties.
@SpringBootApplication
public class TestedValueApplication {
@Autowired
void printServiceInstance(ServiceA service) {
System.out.println("Service instance: " + service);
System.out.println("value==value? " + service.isFieldA("value"));
}
public static void main(String[] args) {
SpringApplication.run(TestedValueApplication.class, args);
}
@Bean
public ServiceA serviceA(@Value("${fieldA}") String fieldA) {
return new ServiceAImpl(fieldA);
}
}
Service:
public class ServiceAImpl implements ServiceA {
private String fieldA;
ServiceAImpl(String fieldA) {
this.fieldA = fieldA;
}
public boolean isFieldA(String text) {
return fieldA.equals(text);
}
}
application.properties:
fieldA=value