英文:
Access both runtime argument and other beans in a spring bean's constructor
问题
我在一个Spring Boot应用程序中有两个bean:
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Shape {
@Resource
private ShapeService shapeService;
private String name;
private String description;
public Shape(String name) {
this.name = name;
this.description = shapeService.getDescription();
}
}
@Service
public class ShapeService {
public String getDescription() {
return "This is a shape.";
}
}
我使用以下代码创建了Shape
实例:
Shape shape = beanFactory.getBean(Shape.class, "shape");
但是在以下代码行上,我遇到了NullPointerException
:
this.description = shapeService.getDescription();
shapeService
为null。有没有办法在Shape
的构造函数内部使用shapeService
?
<details>
<summary>英文:</summary>
I have two beans in a spring-boot application:
```java
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Shape {
@Resource
private ShapeService shapeService;
private String name;
private String description;
public Shape(String name) {
this.name = name;
this.description = shapeService.getDescription();
}
}
@Service
public class ShapeService {
public String getDescription() {
return "This is a shape.";
}
}
I created the Shape
instance using the following code:
Shape shape = beanFactory.getBean(Shape.class, "shape");
But I got a NullPointerException
on the following line:
this.description = shapeService.getDescription();
shapeService
is null. Is there any way to use shapeService
inside Shape
's constructor?
答案1
得分: 1
问题在于在Spring可以对其进行字段注入之前,必须先创建一个对象。因此,您正在引用的字段尚未被Spring设置,但在对象完全构建之后将被设置。如果那行代码在常规方法中,它将起作用。
为了解决这个问题,您必须让Spring通过构造函数参数将对ShapeService
的引用传递给构造函数。将您的Shape
类的代码更改如下:
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Shape {
private ShapeService shapeService;
private String name;
private String description;
public Shape(String name, ShapeService shapeService) {
this.name = name;
this.shapeService = shapeService;
this.description = shapeService.getDescription();
}
}
即使在您的情况下不是必需的,我更喜欢构造函数参数注入,而不是自动装配。构造函数注入通常被认为是更好的形式。这篇文章解释了为什么。
英文:
The problem is that Spring has to create an object before it can do field injection on it. So the field you are referencing hasn't been set yet by Spring, but will be later on, after the object is fully constructed. If that line were in a regular method, it would work.
To fix this, you have to have Spring pass the reference to your ShapeService
to your constructor via a constructor argument. Change your code for your Shape
class to look like this:
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Shape {
private ShapeService shapeService;
private String name;
private String description;
public Shape(String name, ShapeService shapeService) {
this.name = name;
this.shapeService = shapeService;
this.description = shapeService.getDescription();
}
}
I prefer constructor argument injection over autowiring even if it isn't necessary, like it is in your case. Constructor injection is generally considered to be better form. Here's an article that explains why
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论