Springで自己インスタンス化されたオブジェクトに依存関係を注入する方法は?


128

クラスがあるとしましょう:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

次に、このクラスのオブジェクトを作成しました(または他のフレームワークがこのクラスのインスタンスを作成しました)。

MyClass obj = new MyClass();

依存関係を注入することはまだ可能ですか?何かのようなもの:

applicationContext.injectDependencies(obj);

(Google Guiceには次のようなものがあると思います)

回答:


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/...
ショーン・パトリック・フロイド

しかし、2つのオブジェクトがあり、最初にオートワイヤーが2番目にある場合はどうでしょう。Autowire Beanファクトリは、ケースの依存関係をどのように扱いますか?
Vadim Kirilchuk 2014年

3
これは実際には悪いパターンです。これが実際にMyBeanを使用する方法である場合は、AnotherBeanをパラメーターとして使用するコンストラクターを用意しないでください。のようなもの: codeプライベート@Autowired AnotherBean Bean; public void doStuff(){MyBean obj = new MyBean(bean); } code。これらのすべての注釈と同じように思われ、人々は本当に混乱し、1日目からJava SDKにあった基本的なパターンを使用しません:(
Denis

3
私は同意します-Springは言語全体を再定義しました。今、私たちはインターフェースを具象クラスとして使用し、メソッドをクラスインスタンスとして使用し、新しくてまともなデザインで行っていたものを実行するための複雑でコードが重いすべての方法を使用します。
Rodney P. Barbati、2015

@Denis MyBeanに実際のクラスに必要のない依存関係がある場合、クラスをインスタンス化するためだけに、実際には存在しない依存関係を登録するため、違いはありません。
ダルトン

17

MyClassに@Configurableアノテーションを付けることもできます。

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

次に、作成時に依存関係を自動的に挿入します。また<context:spring-configured/>、アプリケーションコンテキストxmlにも必要です。


2
Galz666、あなたの方法は私がやりたいことに対してはるかにきれいに見えます。しかし、私はそれを機能させることができません。私にはxmlファイルがなく、完全にJava設定を使用しています。に相当するものはあり<context:spring-configured/>ますか?
2014

1
これはクリーンなソリューションですが、もう少し労力が必要です。iimuhinが上に示すように、ロード時のウィービングを使用するか、プロジェクトにAspectJコンパイラーを追加する必要があります。名前が示すようにロード時間は、実行時に追加のコストを引き起こします。
jsosnowski 2015

4

同じ必要性を得ただけで、私の場合、Springで管理できないjavaクラス内のロジックにアクセスできましたApplicationContext。scaffmanに触発されました。解決者:

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. GradleとEclipse

手順

機能させるには、以下の手順に従う必要がありました

  1. @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)あなたの上に置かれるようにBean手動でインスタンス化することです。私の場合、Bean手動でインスタンス化されるものには@Autowiredサービスがあるため、上記の注釈の小道具です。
  2. 春ブーツの主な注釈付けXXXApplicaiton.java(またはでアノテートされたファイルを@SpringBootApplication持つ)@EnableSpringConfiguredと、@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
  3. (あなたが使用している1に応じて、すなわち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どこにでも注釈が付けられており、その依存関係は自動配線されているはずです。

*上記のポイント#3に関して、私は(ここでmavencentralに示されているようにorg.springframework.boot:spring-boot-starter-aop推移的にプルすることを認識していspring-aopますが、私の場合、Eclipseが注釈を解決できなかったため、スターターに加えて依存関係を明示的に追加しました。同じ問題に直面した場合は、依存関係を宣言するか、理解するという冒険に進んでください@EnableSpringConfiguredspring-aop

  • バージョンの競合はありますか
  • なぜ org.springframework.context.annotation.aspect.*利用できない
  • IDEは正しくセットアップされていますか
  • など
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.