4

我在将 bean 注入辅助类时遇到问题。它的工作原理基本上是这样的:我在页面构造函数中创建了一个对象,它做了一些工作,返回一些数据,然后我在页面上显示这些。在这个辅助对象中,应该通过@Autowired注解注入服务。但是,当我使用它时,我总是得到一个空指针异常。我也尝试过@SpringBean,但没有帮助。另一方面,当我将此服务直接注入带有 的页面时@SpringBean,它可以访问并且工作正常。你知道问题出在哪里吗?

这是页面:

public class Page extends BasePage {
    public Page() {
        HelperObject object = new HelperObject(new Application("APP_NAME"));
        String result = object.getData();

        add(new Label("label", result));
    }
}

辅助对象:

public class HelperObject {
    private Application app;

    @Autowired
    private Service service;

    public HelperObject(Application app) {
        this.app = app;
    }

    public String getData() {
        // use service, manipulate data, return a string
    }
}
4

3 回答 3

5

@SpringBean您可以通过调用InjectorHolder.getInjector().inject(this);其构造函数将依赖项注入到非 Spring-non-Wicket-new-created 对象中。

例如:

class MyPojo {
    @SpringBean
    MyDumbDAO dao;
    MyPojo() {
        InjectorHolder.getInjector().inject(this);
    }
    void justDoIt() {
        dao.duh(); // dao is there!
    }
}

请注意,只有在 Wicket 管理的请求中调用它才会起作用。如果不是(即,如果它是 Quartz 作业,或者是在 Wicket 之前执行的过滤器),则该Application实例将不可用,并且注入器将不知道如何获取依赖项。

另一种解决方案是使用 Spring 的@Configurable. 它使用 AspectJ 拦截带注释对象的创建,并注入其依赖项,即使您直接使用new(或其他一些框架,如 Hibernate,在内部创建它们)实例化它们也是如此。但这需要运行时或构建时(对我来说效果更好)字节码操作,这对某些人来说可能太神奇了。

于 2011-03-24T12:56:51.520 回答
3

@SpringBean仅将依赖项注入从 Wicket 继承的类中Component@Autowired仅将依赖项注入 Spring 自身创建的类中。这意味着您不能自动将依赖项注入您使用创建的对象中new

(编辑:您还可以@SpringBean通过在构造函数中注入来向您的类添加注入 InjectorHolder.getInjector().inject(this);:)

我通常的解决方法是使用我的应用程序类来提供帮助。(我对你对 . 的使用感到有些困惑new Application(...)。我认为这实际上不是org.apache.wicket.Application。)例如:

public class MyApplication extends AuthenticatedWebApplication implements
    ApplicationContextAware {

    private ApplicationContext ctx;

    public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
        this.ctx = applicationContext;
    }

    public static MyApplication get() {
        return (MyApplication) WebApplication.get();
    }

    public static Object getSpringBean(String bean) {
        return get().ctx.getBean(bean);
    }

    public static <T> T getSpringBean(Class<T> bean) {
        return get().ctx.getBean(bean);
    }

    ....
}

在我的 Spring 应用程序上下文中:

<!-- Set up wicket application -->
<bean id="wicketApplication" class="uk.co.humboldt.Project.MyApplication"/>

然后我的助手对象按需查找服务:

public class HelperObject {

    private Service getService() {
        return MyApplication.getSpringBean(Service.class);
    }
于 2011-03-24T12:30:46.697 回答
3

最佳实践是通过工厂 bean 创建您的对象(具有由 Spring 注入的那些属性,并让该工厂将这些属性注入它产生的对象 - 纯 IoC)。

你真的应该避免到处使用 SpringContext(或任何其他类似的解决方案)。以下是部分原因列表:

  1. 您的代码与 Spring 耦合太多(低内聚性)。
  2. 您将管道代码与业务逻辑混合在一起。
  3. 您的代码可读性较差。
  4. 它的可维护性较差(例如,更改服务 bean 的名称会导致代码修改——这违反了 SRP 和 OCP)。
  5. 它的可测试性较低(例如,您需要 Spring 框架来测试它)。
于 2013-07-21T20:13:02.647 回答