访问Spring Bean构造函数中的运行时参数和其他Bean。

huangapple go评论142阅读模式
英文:

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 &quot;This is a shape.&quot;;
    }
}

I created the Shape instance using the following code:

Shape shape = beanFactory.getBean(Shape.class, &quot;shape&quot;);

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

huangapple
  • 本文由 发表于 2020年10月5日 23:17:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/64211467.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定