You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 14:45:04