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

假设我们有一堂课:

public class MyClass {
@Autowired private AnotherBean anotherBean;
}

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

MyClass obj = new MyClass();

是否仍然可以注入依赖项? 比如:

applicationContext.injectDependencies(obj);

(我认为 Google Guice 有类似的东西)

83587 次浏览

您可以使用 AutowireCapableBeanFactoryautowireBean()方法来完成这项工作。您传递给它一个任意的对象,Spring 将把它看作是它自己创建的对象,并应用各种自动连接位和片段。

要拿到 AutowireCapableBeanFactory,只需自动接线:

private @Autowired AutowireCapableBeanFactory beanFactory;


public void doStuff() {
MyBean obj = new MyBean();
beanFactory.autowireBean(obj);
// obj will now have its dependencies autowired.
}

你也可以用@Configable 注释来标记你的 MyClass:

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

然后在创建时它会自动注入它的依赖项。

只是得到了同样的需要,在我的情况下,它已经是非 Spring 可管理的 java 类中的逻辑,可以访问 ApplicationContext。灵感来自脚手架工。 解决方法:

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

我想分享我的解决方案,遵循 @Configurable的方法,如 briefly在@glaz666回答中提到的,因为

  • 由@skaffman 设计的 回答已经有将近10年的历史了,但这并不意味着它不够好或者不起作用
  • @ glaz666给出的答案很简短,并没有真正帮助我解决问题,但的确为我指明了正确的方向

我的装置

  1. SpringBoot2.0.3和 Spring Neo4j & Aop starts(这无关紧要)
  2. 使用 @Configurable方法(使用 ApplicationRunner)在 Spring Boot就绪时实例化 bean
  3. 格拉德尔 & 日食

步骤

我需要遵循下面的步骤,以便让它工作

  1. 将放置在 Bean之上的 @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)将被手动实例化。在我的案例中,将被手动实例化的 Bean具有 @Autowired服务,因此支持上述注释。
  2. @EnableSpringConfigured@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)注释 Spring 引导的主 XXXApplicaiton.java(或用 @SpringBootApplication注释的文件)
  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 设置是否正确
  • 等等。

我用了另一种方法。我有一些弹簧加载的 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;
}
}

这对我很有效:

@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}

查看更多信息: https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html