简体   繁体   English

Spring 引导无法使用@Value 进行注入

[英]Spring Boot Failed to use @Value for injection

Spring Boot version <version>2.2.0.RELEASE</version> Spring 引导版本<version>2.2.0.RELEASE</version>

Error goes as follows:错误如下:

Description:描述:

Parameter 2 of constructor in com.shawn.foodrating.service.impl.AdServiceImpl required a bean of type java.lang.Integer that could not be found. com.shawn.foodrating.service.impl.AdServiceImpl java.lang.Integer的 bean。

Action:行动:

Consider defining a bean of type 'java.lang.Integer' in your configuration.考虑在你的配置中定义一个“java.lang.Integer”类型的bean。

My Code:我的代码:

@Service
@Transactional(rollbackOn = Exception.class)
@AllArgsConstructor
public class AdServiceImpl implements AdService {
 private AdRepository repository;
 private FileService fileService;
 @Value("${app.ad.DefaultPageSize}")
 private Integer DEFAULT_PageSize;
 @Value("${app.ad.ImagePath}")
 private String AD_IMAGE_PATH;
 @Value("${app.ad.ImageUrl}")
 private String AD_IMAGE_URL;

Load property file加载属性文件


@SpringBootApplication
@PropertySource("classpath:app.properties")
public class FoodRatingApplication {
    public static void main(String[] args) {
        SpringApplication.run(FoodRatingApplication.class, args);
    }

}

Not Sure what is wrong with it.不确定它有什么问题。

When you use Lombok's @AllArgsConstructor it must create a constructor for all your fields, those annotated with @Value and those that aren't.当您使用 Lombok 的@AllArgsConstructor时,它必须为您的所有字段创建一个构造函数,那些带有@Value注释的字段和那些没有注释的字段。

Now Lombok doesn't even know anything about @Value annotation of spring.现在 Lombok 甚至对 spring 的@Value注释一无所知。 So the generated constructor looks something like this:所以生成的构造函数看起来像这样:

public AdServiceImpl(AdRepository repository, FileService fileService, Integer DEFAULT_PageSize, String AD_IMAGE_PATH, String AD_IMAGE_URL) {
   this.repository = repository;
   ....
}

You can run Delombok to see the actually generated code.您可以运行 Delombok 来查看实际生成的代码。

Spring on the other hand when sees a single constuctor tries to call it to create the bean ( AdServiceImpl ) in this case, and only after that iterates through its fields and inject data annotated by @Value .另一方面,Spring 在这种情况下看到单个构造函数尝试调用它来创建 bean ( AdServiceImpl ),并且只有在此之后迭代其字段并注入由@Value注释的数据。

Now, when spring calls the constructor, it sees an integer (DEFAULT_PageSize), has no clue that its a value (and spring has to inject something brcause its a constructor injection), and throws an Exception. Now, when spring calls the constructor, it sees an integer (DEFAULT_PageSize), has no clue that its a value (and spring has to inject something brcause its a constructor injection), and throws an Exception.

So in terms of resolution:所以在分辨率方面:

Don't use all args constructor of lombok in this case and instead create a non-lombok constructor for AdRepository and FileService only)在这种情况下不要使用 lombok 的所有 args 构造函数,而是只为AdRepositoryFileService创建一个非 lombok 构造函数)

Alternatively create a constructor with @Value annotated parameters instead of field injection (remove @Value on fields):或者使用 @Value 注释参数创建构造函数,而不是字段注入(删除字段上的 @Value):

public AdServiceImpl(AdRepository repository, FileService fileService, @Value(${app.ad.DefaultPageSize}"} Integer DEFAULT_PageSize, @Value(...) String AD_IMAGE_PATH, @Value(...) String AD_IMAGE_URL) {
   this.repository = repository;
   ....
}

Add to projeck lombok.config file with this lines:使用以下行添加到 projeck lombok.config 文件:

lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Value

The root cause is that you are using Lombok @AllArgsConstructor while some of the properties are populated by @Value(..) .根本原因是您使用 Lombok @AllArgsConstructor而某些属性由@Value(..)填充。

Replace the @AllArgsConstructor with @RequiredArgsConstructor and give it a try.将 @AllArgsConstructor 替换为@RequiredArgsConstructor并试一试。

Note: Adding this comment for future references.注意:添加此评论以供将来参考。

You can use in the following manner.您可以按以下方式使用。

@Service
@Configuration
@ComponentScan
@PropertySource("classpath:app.properties")
@Transactional(rollbackOn = Exception.class)
@AllArgsConstructor
public class AdServiceImpl implements AdService {
 private AdRepository repository;
 private FileService fileService;
 @Value("${app.ad.DefaultPageSize}")
 private Integer DEFAULT_PageSize;
 @Value("${app.ad.ImagePath}")
 private String AD_IMAGE_PATH;
 @Value("${app.ad.ImageUrl}")
 private String AD_IMAGE_URL;

To use @Value annotation, you have to use @Configuration and @PropertySource in the same class.要使用@Value注解,您必须在同一个 class 中使用@Configuration@PropertySource

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM