弹簧动态注塑,工厂般的图案

从dependency injection的延续,延迟注射实践 。 我有Main课程:

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 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 getStringList(); } package test; import org.springframework.stereotype.Component; import java.util.ArrayList; @Component public class StringList extends ArrayList { } 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 stringList; @Inject public StringService(final ArrayList 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 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 stringList; private List validationList; private final List validatedList = new ArrayList(); @Autowired public StringValidator(final ArrayList stringList, final ArrayList 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 getValidatedList() { return validatedList; } } package test; import java.util.List; public interface Validateable { List getValidationList(); } package test; import org.springframework.stereotype.Component; import java.util.ArrayList; @Component public class ValidationList extends ArrayList { } 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 validationList; @Inject public ValidationService(final ArrayList 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 getValidationList() { return validationList; } } 

有没有人知道如何解决方法调用createList()或createSecondList() – 而不使用几乎强制设计的构造函数。 我在想一家工厂,但是在一个更大规模的项目中,每个class级的工厂似乎都不是一个好主意。

就像是:

  

并在工厂方法实例化该类并调用方法createList()。 或者像这样调用它,从某种方法 – 再次看起来很糟糕,迫使方法有责任实例化对象图。

我想在运行时解析的运行时依赖项的图片如下:

在此处输入图像描述

有没有其他方法我可以使用容器来实现动态懒惰的初始化取决于用户交互?

谢谢。

如果您希望在每次调用相应的getter时动态初始化/填充类的某个成员,则可以尝试查找方法注入。 请阅读第3.3.4.1页

因此,即使包含动态成员的类是在scope=singletone (spring bean容器的缺省值)中创建的,每次访问已分配查找方法的字段时,您将根据内部实现的业务逻辑获取适当的对象查找方法。 在您的情况下,列表是一个接口,因此您可以在查找方法中轻松实现validation并返回经过validation的列表。

编辑:

我在Spring文档中找到了更好的例子 – 我认为它非常清楚。 看看“3.4.6.1 Lookup方法注入”

当您配置Main类为其List成员分配查找方法时 – 只要您需要List bean的新实例,它就会被调用。

祝你好运!

Spring专为可重用组件注入而设计,不适用于业务数据操作和注入。

实际上,一些数据用于dependency injection,但仅用于配置组件行为,而不是用于创建业务数据持有者。

顺便说一下,在您的情况下可以使用以下选项:感谢BeanFactory与BeanFactoryAware接口以及使用scope =“prototype”,您可以通过调用getBean()来生成bean,就像在该示例中或从其他问题:按需创建bean 。

如果你准备的bean数量有限,那么另一个选择是使用通用bean创建,就像缺少bean被模拟一样

现在考虑Spring永远不会在其Context中收集bean。 因此,创建Spring bean来保存业务数据对于内存消耗是有风险的。

如果你的目标不同(我希望如此),也许你正试图通过自己的多租户支持来实现。 Spring提供租赁 ,以防您有不同的业务上下文来实现特定的组件或行为。

听起来用户可以选择对象的1..N图形,而您只想加载用户在运行时选择的图形。 如果图形在设计时已知,但用户只选择他们想要的图形,那么它听起来就像你拥有的是一堆ApplicationContexts而你只想加载用户在运行时选择的一个ApplicationContext。 那么为什么不定义ApplicationContexts集合,然后在运行时实例化正确的ApplicationContexts集合。 由于Spring支持Java Config,因此将这些配置定义为Java类可能是有意义的,这样您就可以获得inheritance并避免剪切/粘贴任何代码。