使用 @Autowired 将依赖项注入到使用“new ...”创建的对象中

发布于 2024-10-26 21:11:27 字数 811 浏览 6 评论 0原文

我在将 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
    }
}

I have a problem with injecting a bean into a helper class. It works basically like this: I create an object in the page constructor that does some work, returns some data and I show these on the page. In this helper object, a service should be injected via @Autowired annotation. However, I always get a null pointer exception when I use it. I also tried @SpringBean but it didn't help. On the other hand, when I inject this service directly into the page with @SpringBean, it's accessible and works fine. Do you know where the problem is?

This is the page:

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

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

Helper object:

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
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不醒的梦 2024-11-02 21:11:27

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

例如:

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

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

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

You can inject dependencies into non-Spring-non-Wicket-new-created objects using @SpringBean by calling InjectorHolder.getInjector().inject(this); in its constructor.

For example:

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

Note that it will only work if called within a Wicket-managed request. If not (ie, if it's a Quartz job, or a Filter executed before Wicket's), the Application instance will not be available, and the injector won't know how to get the dependencies.

Another solution is to use Spring's @Configurable. It uses AspectJ to intercept creation of annotated objects, and inject its dependencies, even if you instantiate them directly with new (or some other framework, like Hibernate, creates them internally). But this requires runtime or build-time (works better for me) bytecode manipulation, which may be too much magic for some people.

握住我的手 2024-11-02 21:11:27

@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);
    }

@SpringBean only injects dependencies into classes that inherit from Wicket's Component. @Autowired only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create with new.

(Edit: you can also add a @SpringBean injection to your class by injecting in the constructor:
InjectorHolder.getInjector().inject(this);)

My normal workaround for this is to use my application class to help. (I'm a little puzzled by your use of new Application(...). I assume this isn't actually org.apache.wicket.Application.) For example:

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);
    }

    ....
}

In my Spring application context:

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

My helper object then looks up the service on demand:

public class HelperObject {

    private Service getService() {
        return MyApplication.getSpringBean(Service.class);
    }
ゝ杯具 2024-11-02 21:11:27

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

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

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

The best practice would be to create your objects via a factory bean (that has those properties injected by Spring, and have that factory inject those properties to objects it spawns - pure IoC).

You should really avoid using SpringContext all over the place (or any other similar solution for that matter).
Here is a partial list of reasons:

  1. Your code gets coupled with Spring way too much (low-cohesion).
  2. You mix plumbing code with the business-logic.
  3. Your code is less readable.
  4. It's less maintainable (e.g., changing the name of the service bean would lead to code modification - this violates SRP & OCP).
  5. It's less testable (e.g., you need the Spring framework to test it).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文