如何在我的自定义Wicket模型类中注入Spring bean?

Jon*_*nik 12 java spring wicket dependency-injection

在一个自定义的Wicket类中,与以下不同,我使用的是一个应该由Spring注入的服务bean,如SpringBean注释(来自wicket-spring项目)所定义的.

public class ReportExportFileModel extends AbstractReadOnlyModel<File> {

    @SpringBean(name = "reportService")
    ReportService reportService;

    ReportDto reportDto;

    ReportExportFileModel(ReportDto reportDto) {
        this.reportDto = reportDto;
    }

    @Override
    public File getObject() {
        try {
            return reportService.generatePentahoReport(reportDto);
        } catch (ReportGenerationException e) {
           // ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用:reportService.generatePentahoReport()使用NullPointerException失败,因为由于某种原因,Spring没有注入bean.

奇怪的是,我在Wicket页面上使用完全相同的模型代码作为匿名内部类,并且没有问题.

我怎样才能解决这个问题?

ber*_*nie 16

wicket依赖注入与实现IComponentInstantiationListener的类一起使用.只要实例化Component,就会调用这些应用程序级侦听器.这是用于依赖注入组件的钩子.

模型类没有这样的机制.任何模型都可以直接实现IModel,因此与Component不同,没有可以调用侦听器的抽象基类.

我为注入的模型使用以下基类(Wicket 1.5):

public abstract class InjectedDetachableModel<T> extends LoadableDetachableModel<T> {

    public InjectedDetachableModel() {
        Injector.get().inject(this);
    }

    public InjectedDetachableModel(T a_entity) {
        super(a_entity);
        Injector.get().inject(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:1.4和1.5之间的相关差异摘要,取自Wicket 1.5迁移指南:

Wicket 1.4

@Override
protected void init()
{
    // initialize Spring
    addComponentInstantiationListener(new SpringComponentInjector(this, applicationContext));
}
Run Code Online (Sandbox Code Playgroud)

InjectorHolder.getInjector().inject(Object object)
Run Code Online (Sandbox Code Playgroud)

Wicket 1.5:

@Override
protected void init()
{
    // initialize Spring
    getComponentInstantiationListeners().add(new SpringComponentInjector(this, applicationContext))
}
Run Code Online (Sandbox Code Playgroud)

Injector.get().inject(Object object)
Run Code Online (Sandbox Code Playgroud)


Jon*_*nik 7

显然,Spring bean不会自动注入除Pages之外的其他类.我也使用自定义WebRequestCycle类来运行此操作.

一个简单的解决方案是使用手动触发注射InjectorHolder.getInjector().inject(this).

因此,像这样编写构造函数使模型按预期工作:

ReportExportFileModel(ReportDto reportDto) {
    this.reportDto = reportDto;
    InjectorHolder.getInjector().inject(this);
}
Run Code Online (Sandbox Code Playgroud)

编辑:嗯,在发布这个之后,我发现了另一个SO问题,更准确地解释了发生了什么:

@SpringBean仅适用于Component的任何子类.