Injecting dependencies using @Autowired into objects created with “new …”

偶尔善良 提交于 2019-12-03 16:28:58

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

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.

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).
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!