如何在Spring中将依赖项注入自我实例化的对象?

时间:2010-09-28 14:04:42

标签: java spring dependency-injection

假设我们有一个班级:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

然后我们创建了这个类的对象(或者其他一些框架创建了这个类的实例)。

MyClass obj = new MyClass();

是否仍然可以注入依赖项?类似的东西:

applicationContext.injectDependencies(obj);

(我认为Google Guice有这样的东西)

6 个答案:

答案 0 :(得分:169)

您可以使用autowireBean()的{​​{1}}方法执行此操作。你将它传递给一个任意对象,Spring将它视为它自己创建的东西,并将应用各种自动装配的零碎。

要掌握AutowireCapableBeanFactory,只需自动启用:

AutowireCapableBeanFactory

答案 1 :(得分:18)

您还可以使用@Configurable注释标记MyClass:

@Configurable
public class MyClass {
   @Autowired private AnotherClass instance
}

然后在创建时它将自动注入其依赖项。您还应该在应用程序上下文xml中有<context:spring-configured/>

答案 2 :(得分:2)

得到了同样的需求,在我的情况下,它已经是非Spring可管理的java类中的逻辑,它可以访问ApplicationContext。受到脚手架的启发。 解决方法:

AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);

答案 3 :(得分:2)

我想与@ glaz666 answer中提到的@Configurable一样遵循briefly方法的解决方案,因为

  • @skaffman的answer年近10岁了,这并不意味着不够好或不起作用
  • @ glaz666的回答很简短,并不能真正帮助我解决问题,但确实为我指明了正确的方向

我的设置

  1. 带有Spring Neo4j & Aop starts的Spring Boot 2.0.3(无论如何都无关紧要)
  2. 使用Spring Boot方法(使用@ConfigurableApplicationRunner准备好实例化Bean
  3. Gradle&Eclipse

步骤

为了使其正常运行,我需要按照以下步骤操作

  1. @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)放在要手动实例化的Bean之上。在我的情况下,要手动实例化的Bean具有@Autowired服务,因此是上述注释的支撑。
  2. XXXApplicaiton.java@SpringBootApplication注释Spring Boot的主@EnableSpringConfigured(或用@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)注释的文件)
  3. 在构建文件中添加依赖项(即build.gradle或pom.xml,取决于您使用的依赖项)compile('org.springframework.boot:spring-boot-starter-aop')compile('org.springframework:spring-aspects:5.0.7.RELEASE')
  4. 在您的Bean处随处新增@Configurable,并自动关联其依存关系。

*关于上述第3点,我知道org.springframework.boot:spring-boot-starter-aop会传递spring-aop的拉动(如此处mavencentral所示),但就我而言,Eclipse无法解决因此,@EnableSpringConfigured批注是为什么我除了入门者之外还明确添加了spring-aop依赖项。如果您遇到相同的问题,只需声明依赖项或继续冒险

  • 是否存在版本冲突
  • 为什么org.springframework.context.annotation.aspect.*不可用
  • 您的IDE是否设置正确
  • 等等。

答案 4 :(得分:0)

我使用了不同的方法。我有弹簧加载的 bean,我想从创建自己线程的第三方库的扩展类中调用它们。

我使用了我在这里找到的方法https://confluence.jaytaala.com/display/TKB/Super+simple+approach+to+accessing+Spring+beans+from+non-Spring+managed+classes+and+POJOs

在非托管类中:

{
    [...]
    SomeBean bc = (SomeBean) SpringContext.getBean(SomeBean.class);

    [...]
    bc.someMethod(...)
}

然后作为主应用程序中的辅助类:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContext implements ApplicationContextAware
{
    private static ApplicationContext context;

    public static <T extends Object> T getBean(Class<T> beanClass)
    {   
        return context.getBean(beanClass);
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException
    {   
        SpringContext.context = context;
    }
}

答案 5 :(得分:-4)

并非没有一些解决方法,因为Spring对此实例一无所知。

真正的问题是:为什么要创建一个类的实例,您希望手动注入依赖项,而不是让Spring控制它?为什么使用MyClass的班级注入了MyClass