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


128

假设我们有一个课程:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

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

MyClass obj = new MyClass();

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

applicationContext.injectDependencies(obj);

(我认为Google Guice有这样的内容)

Answers:


194

您可以使用的autowireBean()方法执行此操作AutowireCapableBeanFactory。您将其传递给一个任意对象,Spring会像对待它自己创建的对象一样对待它,并将应用各种自动装配零碎的零件。

要掌握AutowireCapableBeanFactory,只需自动连线即可:

private @Autowired AutowireCapableBeanFactory beanFactory;

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

好答案(+1)。还有第二种方法可以影响自动装配的方式:static.springsource.org/spring/docs/3.0.x/javadoc-api/org/…–
肖恩·帕特里克·弗洛伊德

但是,如果我有两个对象,然后自动装配第二个,该怎么办?在这种情况下,autowire bean工厂如何处理依赖关系?
Vadim Kirilchuk 2014年

3
这实际上是一个不好的模式。如果这是您真正使用MyBean的方式,那么为什么不只使用带有AnotherBean作为参数的构造函数。像这样: codeprivate @Autowired AnotherBean bean;公共无效doStuff(){MyBean obj = new MyBean(bean); } code。似乎与所有这些注释一样,人们真的很困惑,只是从第一天开始就没有使用Java SDK中的基本模式。:(
Denis

3
我同意-Spring重新定义了整个语言。现在,我们将接口用作具体的类,将方法用作类的实例,并使用各种复杂的代码繁重的方法来完成您以前用新颖而又不错的设计所做的工作。
Rodney P. Barbati

@Denis如果MyBean具有实际类不需要的依赖项,则您注册的是实际上并不存在的依赖项,只是为了实例化一个类,因此实际上没有任何区别。
道尔顿

17

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

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

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


2
Galz666,您的方法对于我想做的看起来更干净。但是我无法使它正常工作。我没有xml文件,并且完全使用Java配置。有相当于<context:spring-configured/>吗?
masstroy 2014年

1
这是一个干净的解决方案,但需要付出更多的努力:您应该使用上面iimuhin所示的加载时编织,或者将AspectJ编译器添加到项目中。顾名思义,加载时会在运行时引起额外的成本。
jsosnowski

4

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

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

3

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

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

我的设定

  1. Spring Boot 2.0.3 with Spring Neo4j & Aop starts(无论如何都不相关)
  2. Spring Boot准备使用@Configurable方法实例化Bean (使用ApplicationRunner
  3. 摇篮和日食

脚步

我需要按照以下步骤操作

  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. 新建Bean@Configurable在任何地方添加注释,并且其依赖项应自动装配。

*关于上面的第3点,我知道org.springframework.boot:spring-boot-starter-aop传递性地拉了spring-aop(如mavencentral所示),但是,在我的情况下,Eclipse无法解析@EnableSpringConfigured注释,因此,为什么我spring-aop在启动程序之外显式添加了依赖项。如果您遇到相同的问题,只需声明依赖项或继续探索

  • 是否存在版本冲突
  • 为什么 org.springframework.context.annotation.aspect.*不可用
  • 您的IDE设置正确吗
  • 等等
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.