依存性注入、遅延注入の実践 からの続き。私はメインクラスを持っています:
package test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import Java.util.List;
import Java.util.Scanner;
@Component
public class Main {
@Autowired
private StringValidator stringValidator;
@Autowired
private StringService stringService;
@Autowired
private ValidationService validationService;
public void main() {
scanKeyboardCreateLists();
stringValidator.validate();
final List<String> validatedList = stringValidator.getValidatedList();
for (String currentValid : validatedList) {
System.out.println(currentValid);
}
}
private void scanKeyboardCreateLists() {
//Let's presume the user interacts with the GUI, dynamically changing the object graph...
//Needless to say, this is past container initialization...
Scanner scanner = new Scanner(System.in);
int choice = scanner.nextInt();
//Delayed creation, dynamic
if (choice == 0) {
stringService.createList();
validationService.createList();
} else {
stringService.createSecondList();
validationService.createSecondList();
}
}
public static void main(String[] args) {
ApplicationContext container = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml");
container.getBean(Main.class).main();
}
}
また、オブジェクトグラフは、ユーザーの操作に応じて動的に作成されます。アプリケーションの結合を解決し、これを非常に簡単にテストできるようにしました。 また、リストはコンテナによって維持されるため、このアプリケーション(および他のすべて)の動的な性質は関係ありません。アプリケーションがリストを必要とするときにいつでも要求でき、要素を維持できるからです。
残りのコードはここにあります:
package test;
import Java.util.List;
public interface Stringable {
List<String> getStringList();
}
package test;
import org.springframework.stereotype.Component;
import Java.util.ArrayList;
@Component
public class StringList extends ArrayList<String> {
}
package test;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import Java.util.ArrayList;
import Java.util.List;
@Component
public class StringService implements Stringable {
private List<String> stringList;
@Inject
public StringService(final ArrayList<String> stringList) {
this.stringList = stringList;
}
//Simplified
public void createList() {
stringList.add("FILE1.txt");
stringList.add("FILE1.dat");
stringList.add("FILE1.pdf");
stringList.add("FILE1.rdf");
}
public void createSecondList() {
stringList.add("FILE2.txt");
stringList.add("FILE2.dat");
stringList.add("FILE3.pdf");
stringList.add("FILE3.rdf");
}
@Override
public List<String> getStringList() {
return stringList;
}
}
package test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import Java.util.ArrayList;
import Java.util.List;
@Component
public class StringValidator {
private List<String> stringList;
private List<String> validationList;
private final List<String> validatedList = new ArrayList<String>();
@Autowired
public StringValidator(final ArrayList<String> stringList,
final ArrayList<String> validationList) {
this.stringList = stringList;
this.validationList = validationList;
}
public void validate() {
for (String currentString : stringList) {
for (String currentValidation : validationList) {
if (currentString.equalsIgnoreCase(currentValidation)) {
validatedList.add(currentString);
}
}
}
}
public List<String> getValidatedList() {
return validatedList;
}
}
package test;
import Java.util.List;
public interface Validateable {
List<String> getValidationList();
}
package test;
import org.springframework.stereotype.Component;
import Java.util.ArrayList;
@Component
public class ValidationList extends ArrayList<String> {
}
package test;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import Java.util.ArrayList;
import Java.util.List;
@Component
public class ValidationService implements Validateable {
private List<String> validationList;
@Inject
public ValidationService(final ArrayList<String> validationList) {
this.validationList = validationList;
}
//Simplified...
public void createList() {
validationList.add("FILE1.txt");
validationList.add("FILE2.txt");
validationList.add("FILE3.txt");
validationList.add("FILE4.txt");
}
public void createSecondList() {
validationList.add("FILE5.txt");
validationList.add("FILE6.txt");
validationList.add("FILE7.txt");
validationList.add("FILE8.txt");
}
@Override
public List<String> getValidationList() {
return validationList;
}
}
デザインをかなり強制するコンストラクターを使用せずに、createList()またはcreateSecondList()というメソッド呼び出しを解決する方法を知っている人はいますか?私は工場を考えていましたが、より大きな規模のプロジェクトのすべてのクラスの工場は良い考えではないようです。
何かのようなもの:
<bean ... factory-method="..." depends-on="..." lazy-init="..."/>
そして、ファクトリメソッドでクラスをインスタンス化し、メソッドcreateList()を呼び出します。または、あるメソッドからこのように呼び出します。これも見栄えが悪く、メソッドにオブジェクトグラフをインスタンス化する責任を負わせます。
ランタイムで解決したいランタイム依存関係の図は次のとおりです。
ユーザーの操作に応じて、コンテナーを使用して動的な遅延初期化を実現する方法は他にありますか?
ありがとうございました。
クラスの一部のメンバーを、対応するゲッターを呼び出すたびに動的に初期化/入力する必要がある場合は、ルックアップメソッドインジェクションを試すことができます。 ppを読んでください。 3.3.4.1ここ 。
したがって、動的メンバーを含むクラスがscope=singletone
(Spring Beanコンテナーのデフォルト)で作成された場合でも、ルックアップメソッドが割り当てられているフィールドにアクセスするたびに、ビジネスロジックに従って適切なオブジェクトを取得します。 lookupメソッド内に実装されています。あなたの場合、リストはインターフェースなので、ルックアップメソッド内に検証を簡単に実装して、検証済みのリストを返すことができます。
編集:
Springのドキュメントで 例 の方が良いと思いました-非常に明確だと思います。 「3.4.6.1ルックアップメソッドインジェクション」をご覧ください
Main
クラスを構成するとき、ルックアップメソッドをそのList
メンバーに割り当てます-List
Beanの新しいインスタンスが必要になるたびに呼び出されます。
幸運を!
Springは、ビジネスデータの操作や挿入ではなく、再利用可能なコンポーネントの挿入用に設計されています。
実際、一部のデータは依存性注入で使用されますが、コンポーネントの動作を構成するためだけに使用され、ビジネスデータホルダーを作成するためには使用されません。
ちなみに、あなたのケースでは次のオプションを使用できます:BeanFactory
with BeanFactoryAware interface とscope = "prototype"の使用により、getBean()
を呼び出すことでBeanを生成できます。 その例 または その他の質問:オンデマンドでBeanを作成する のように。
準備するBeanの数が限られている場合の代替オプションは、一般的なBean作成を使用することです 不足しているBeanがモックされるのと同じ方法
ここで、SpringがそのコンテキストでBeanをガベージ収集しないことを考慮してください。したがって、ビジネスデータを保持するSpring Beanを作成すると、メモリを消費するリスクがあります。
目的が異なる場合(そう願っています)、マルチテナントサポートを独自に実装しようとしている可能性があります。 Springは、特定のコンポーネントまたは動作で実装するビジネスコンテキストが異なる場合に備えて、tenancyを提供します。
ユーザーがオブジェクトの1..Nグラフを選択でき、実行時にユーザーが選択したグラフのみをロードしたいようです。グラフが設計時にわかっているが、ユーザーが必要なグラフを選択するだけの場合、あなたが持っているのは一連のApplicationContextであり、ユーザーが実行時に選択した1つのApplicationContextのみをロードしたいように思えます。では、ApplicationContextのセットを定義してから、実行時に適切なものをインスタンス化してみませんか。 SpringはJava Configをサポートしているため、これらの構成をJavaクラスとして定義すると、継承を取得してコードの切り取り/貼り付けを回避できるようになります。