RestController POJO中的Spring依赖注入

时间:2018-10-23 03:57:34

标签: java spring spring-boot jackson

有没有一种方法可以将依赖项注入到Spring RestControllers提供的POJO中?例如,如果您想实现多态行为。

下面的示例以NullPointerExcetion失败,因为lowerCaseService没有注入到Example POJO中:

@RestController
public class ExampleController {

  @PostMapping("/example")
  String example(@RequestBody Example example) {
    return example.valueToLowerCase();
  }

}

@Data
@NoArgsConstructor
public class Example {

  private String value;

  @Autowired
  private LowerCaseService lowerCaseService;

  public String valueToLowerCase() {
    return lowerCaseService.toLowerCase(getValue());
  }

}

@Service
public class LowerCaseService {
  public String toLowerCase(String value) {
    return value != null ? value.toLowerCase() : null;
  }
}

请注意,这个人为设计的示例刻意简单,不需要多态行为。我以这种方式创建了它,以帮助响应者快速理解它,而不会被Jackson的注释所困扰。在我的实际用例中,Jackson会生成Example的子类,每个子类都需要做非常不同的事情,并具有不同的依赖关系。

3 个答案:

答案 0 :(得分:1)

根据定义,POJO(普通的旧Java对象)是普通的Java对象类(即,不是JavaBean,EntityBean等),并且不充当任何其他特殊角色,也不实现任何Java框架。这个术语是由Martin Fowler,Rebbecca Parsons和Josh MacKenzie创造的,他们相信通过创建首字母缩写词POJO,此类对象将具有“花哨的名称”,从而使人们确信它们值得使用。链接:https://www.webopedia.com/TERM/P/POJO.html

换句话说,POJO应该只包含属性,而不能包含其他任何内容。

我认为在这种情况下,我们可以通过将服务注入控制器方法来解决问题。

@RestController
public class ExampleController {
  @Autowired
  private LowerCaseService lowerCaseService;

  @PostMapping("/example")
  String example(@RequestBody Example example) {
    return lowerCaseService. toLowerCase(example.getValue);
  }

}

答案 1 :(得分:1)

简单的答案是“不,不能”,因为在Spring的Context中实例化bean时会注入依赖项,而这个POJO只是Jackson映射的一个实例(可能)。

此答案包含更多信息:How does autowiring work in Spring?

但是,比这更重要的是架构原则,您实际上不应该将业务服务放在外部模型中(示例),因为这显然是关注点冲突的分离。

您应该将服务注入控制器类,并将DTO作为参数传递给其方法。

希望有帮助!

答案 2 :(得分:0)

您可以通过实现自己的 RequestBodyAdviceAdapter 来实现您正在尝试做的事情...基本上涉及 3 个步骤:

  1. 创建一个扩展 RequestBodyAdviceAdapter 并实现 ApplicationContextAware 的类(以便您可以访问应用程序上下文)。
  2. 实现supports()方法:
return ((Class) targetType).isAssignableFrom(Example.class);
  1. 覆盖 afterRead() 方法:
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        final Example example = (Example) super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
        final AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        autowireCapableBeanFactory.autowireBeanProperties(example, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
        return example;
}