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

@Autowired构造方法如何传入非Spring托管的自定义变量?

错误原因

被Spring管理的Vaadin路由视图,在容器初始化时会自动解析构造方法的所有参数,要求每个参数都能在Spring上下文找到对应注册的Bean。你把动态传入的业务实体Movie加到构造参数后,Spring会尝试从容器中查找Movie类型的Bean完成注入,但Movie是运行时动态关联的业务数据,不是提前注册到容器的Bean,自然会抛出自动装配失败的错误。

解决方法

不要把动态业务参数放在被@Autowired标记的构造方法里,Vaadin路由视图的动态传参要通过路由参数+生命周期钩子实现,具体实现逻辑如下:

  • 构造方法只保留需要Spring注入的服务类参数,不要加Movie类型的构造入参
  • 实现BeforeEnterObserver接口,在视图进入前从路由参数中读取影片ID,查询得到对应的Movie实体
  • 其他视图跳转时,通过路由参数传递目标影片的ID即可

完整实现代码:

@PageTitle("GiveReview")
@Route(value = "givereview", layout = MainLayout.class)
@PermitAll
public class GiveReviewView extends Div implements BeforeEnterObserver {

    private final AuthenticatedUser authenticatedUser;
    private final ReviewService reviewService;
    private final MovieService movieService;
    private Movie movie;

    @Autowired
    public GiveReviewView(AuthenticatedUser authenticatedUser, ReviewService reviewService, MovieService movieService) {
        this.authenticatedUser = authenticatedUser;
        this.reviewService = reviewService;
        this.movieService = movieService;
    }

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        // 从路由参数中获取影片ID
        Optional<String> movieIdOpt = event.getRouteParameters().get("movieId");
        if (movieIdOpt.isEmpty()) {
            // 未传影片ID时直接转发回影片列表页,避免空指针
            event.forwardTo(MovieListView.class);
            return;
        }
        try {
            Long movieId = Long.parseLong(movieIdOpt.get());
            this.movie = movieService.getById(movieId);
            if (this.movie == null) {
                event.forwardTo(MovieListView.class);
                return;
            }
            // 拿到关联的影片对象后再初始化影评表单
            initForm();
        } catch (NumberFormatException e) {
            event.forwardTo(MovieListView.class);
        }
    }

    private void initForm() {
        // 在这里写影评表单的渲染、提交逻辑,可以直接使用this.movie关联影评
    }
}

其他类跳转到影评页的传参示例:

// 传入目标影片的ID作为路由参数即可
getUI().ifPresent(ui -> ui.navigate(GiveReviewView.class,
        RouteParameters.of("movieId", String.valueOf(currentMovie.getId()))
));

注意:不要在其他业务类中手动newGiveReviewView实例,Vaadin路由视图统一由导航机制触发初始化,手动实例化的视图不会走Spring自动装配逻辑,服务类会出现空指针问题。如果不希望URL暴露影片ID,也可以在跳转前把Movie对象存入Session属性,在beforeEnter方法中取出使用,但路由参数的方案更稳定,刷新页面、分享链接都不会丢失上下文。

内容的提问来源于stack exchange,提问作者Alabama92

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:39:17