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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3813588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:24:06  来源:igfitidea点击:

How to inject dependencies into a self-instantiated object in Spring?

javaspringdependency-injection

提问by Igor Mukhin

Let's say we have a class:

假设我们有一个类:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

Then we created an object of this class (or some other framework have created the instance of this class).

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

MyClass obj = new MyClass();

Is it possible to still inject the dependencies? Something like:

是否仍然可以注入依赖项?就像是:

applicationContext.injectDependencies(obj);

(I think Google Guice has something like this)

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

采纳答案by skaffman

You can do this using the autowireBean()method of AutowireCapableBeanFactory. You pass it an arbitrary object, and Spring will treat it like something it created itself, and will apply the various autowiring bits and pieces.

您可以使用 的autowireBean()方法执行此操作AutowireCapableBeanFactory。你传递给它一个任意对象,Spring 会把它当作它自己创建的东西来对待,并将应用各种自动装配的点点滴滴。

To get hold of the AutowireCapableBeanFactory, just autowire that:

要获得AutowireCapableBeanFactory,只需自动装配:

private @Autowired AutowireCapableBeanFactory beanFactory;

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

回答by glaz666

You can also mark your MyClass with @Configurable annotation:

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

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

Then at creation time it will automatically inject its dependencies. You also should have <context:spring-configured/>in your application context xml.

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

回答by rand0m86

Just got the same need and in my case it was already the logic inside non Spring manageable java class which had access to ApplicationContext. Inspired by scaffman. Solved by:

刚刚得到了同样的需求,在我的情况下,它已经是非 Spring 可管理的 Java 类中的逻辑,它可以访问ApplicationContext. 灵感来自 scaffman。解决者:

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

回答by Raf

I wanted to share my solution that follows the @Configurableapproach as brieflymentioned in @glaz666 answerbecause

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

  • The answerby @skaffman is nearly 10 years old, and that does not mean not good enough or does not work
  • The answer by @glaz666 is brief and didn't really help me solve my problem but, did point me in the right direction
  • @skaffman的答案已经有将近 10 年的历史了,但这并不意味着不够好或不起作用
  • @glaz666 的回答很简短,并没有真正帮助我解决问题,但是确实为我指明了正确的方向

My setup

我的设置

  1. Spring Boot 2.0.3 with Spring Neo4j & Aop starts(which is irrelevant anyway)
  2. Instantiate a bean when Spring Bootis ready using @Configurableapproach (using ApplicationRunner)
  3. Gradle & Eclipse
  1. Spring Boot 2.0.3 with Spring Neo4j & Aop starts(无论如何都无关紧要)
  2. Spring Boot准备好时实例化一个 bean使用@Configurable方法(使用ApplicationRunner
  3. 摇篮和日食

Steps

脚步

I needed to follow the steps below in order to get it working

我需要按照以下步骤操作才能使其正常工作

  1. The @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)to be placed on top of your Beanthat is to be manually instantiated. In my case the Beanthat is to be manually instantiated have @Autowiredservices hence, the props to above annotation.
  2. Annotate the Spring Boot's main XXXApplicaiton.java(or the file that is annotated with @SpringBootApplication) with the @EnableSpringConfiguredand @EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
  3. Add the dependencies in your build file (i.e. build.gradle or pom.xml depending on which one you use) compile('org.springframework.boot:spring-boot-starter-aop')and compile('org.springframework:spring-aspects:5.0.7.RELEASE')
  4. New+up your Beanthat is annotated with @Configurableanywhere and its dependencies should be autowired.
  1. @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)放置在你的上面Bean是手动实例化。在我的情况下Bean,要手动实例化的@Autowired服务因此具有上述注释的道具。
  2. 注释春天启动的主XXXApplicaiton.java(即标注有或文件@SpringBootApplication含)@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. New+up 你的Bean那个在@Configurable任何地方都被注释了,它的依赖项应该是自动装配的。

*In regards to point #3 above, I am aware that the org.springframework.boot:spring-boot-starter-aoptransitively pulls the spring-aop(as shown here mavencentral) but, in my case the Eclipse failed to resolve the @EnableSpringConfiguredannotations hence, why I explicitly added the spring-aopdependency in addition to the starter. Should you face the same issue, just declare the dependency or go on adventure of figuring out

*关于上面的第 3 点,我知道org.springframework.boot:spring-boot-starter-aop传递拉取spring-aop(如这里所示mavencentral)但是,在我的情况下,Eclipse 未能解析@EnableSpringConfigured注释,因此,为什么我spring-aop除了 starter 之外还明确添加了依赖项。如果您遇到同样的问题,只需声明依赖项或继续冒险找出

  • Is there a version conflict
  • Why the org.springframework.context.annotation.aspect.*is not available
  • Is your IDE setup properly
  • Etc etc.
  • 是否有版本冲突
  • 为什么org.springframework.context.annotation.aspect.*不可用
  • 您的 IDE 设置是否正确
  • 等等等等。