基于Vaadin14+Spring Boot+Java11如何避免将服务作为构造参数传递
根本原因
你使用@Autowired字段注入拿到空值,是因为Spring的字段注入逻辑在类实例化完成之后才会执行,你把调用服务的逻辑写在构造函数里的时候,字段还没有完成注入,自然就是null。而构造函数注入是在实例化时就把依赖传入,所以构造函数内可以直接正常使用。
不需要在构造函数传参的解决方法
方案1:字段注入 + @PostConstruct注解
把需要用到注入服务的逻辑从构造函数移到被@PostConstruct修饰的方法中即可,该方法会在所有依赖注入完成后自动触发:
@PageTitle("User Access") @Route(value = "user-access", layout = MainLayout.class) public class UserAccessView extends Div { @Autowired private AccountRoleRepositoryService accountRoleRepositoryService; public UserAccessView() { // 构造函数内仅编写不需要依赖注入的初始化逻辑 } @PostConstruct public void init() { // 所有依赖注入完成后才会执行此处,此时accountRoleRepositoryService已完成赋值 for(AccountRole ar : accountRoleRepositoryService.findAll()){ System.out.println("role: "+ar.getRole()); } } }
注意:Spring Boot 2.x版本导入javax.annotation.PostConstruct,Spring Boot 3+版本导入jakarta.annotation.PostConstruct即可。
方案2:Lombok注解简化构造注入(仅适用于不想手写构造参数的场景)
如果你的诉求只是不想手动编写带参数的构造函数,并非排斥构造注入本身,可以引入Lombok依赖,使用@RequiredArgsConstructor自动生成带所有final字段的构造函数,代码更简洁:
@PageTitle("User Access") @Route(value = "user-access", layout = MainLayout.class) @RequiredArgsConstructor // 自动生成包含所有final修饰成员变量的构造函数 public class UserAccessView extends Div { private final AccountRoleRepositoryService accountRoleRepositoryService; public UserAccessView() { for(AccountRole ar : accountRoleRepositoryService.findAll()){ System.out.println("role: "+ar.getRole()); } } }
补充建议
Spring官方更推荐使用构造注入,可测试性更强(单元测试时可以直接mock依赖传入构造,不需要启动Spring上下文),如果没有特殊需求,更建议保留构造注入的写法,嫌麻烦的话使用上述Lombok方案即可。
内容的提问来源于stack exchange,提问作者jetberay
相关产品推荐
相关产品推荐

