Dependency injection, delayed injection praxis的延续。我有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<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()。 或者像这样调用它,从某种方法 - 再次看起来很糟糕,迫使方法有责任实例化对象图。
我想在运行时解析的运行时依赖项的图片如下:
还有其他方法可以使用容器来实现动态懒惰的初始化,具体取决于用户的互动吗?
谢谢。
答案 0 :(得分:10)
如果您希望在每次调用相应的getter时动态初始化/填充您的类的某个成员,您可以尝试查找方法注入。阅读 pp。 3.3.4.1 here。
因此,即使每次访问分配了查找方法的字段时,包含动态成员的类都是在scope=singletone
(spring bean容器的缺省值)中创建的,您将获得一个适当的对象。在查找方法中实现的业务逻辑。在您的情况下,列表是一个接口,因此您可以在查找方法中轻松实现验证并返回经过验证的列表。
修改强>
我在Spring文档中找到了更好的example - 我认为非常清楚。 看看“3.4.6.1查找方法注入”
当您配置Main
类为其List
成员分配查找方法时 - 只要您需要List
bean的新实例,就会调用它。
答案 1 :(得分:3)
Spring专为可重用组件注入而设计,而不是用于业务数据操作和注入。
确实有一些数据用于依赖注入,但仅用于配置组件行为,而不是创建业务数据持有者。
顺便说一句,在您的情况下可以使用以下选项:感谢BeanFactory
BeanFactoryAware interface并使用scope =“prototype”,您可以通过调用{{1}来生成bean例如that example或that other question: creating bean on demand。
如果您准备的bean数量有限,则可以选择使用通用bean创建the same way lacking beans are mocked
现在考虑Spring永远不会在其Context中收集bean。因此,创建Spring bean来保存业务数据对于内存消耗是有风险的。
如果你的目标不同(我希望如此),也许你正试图通过自己的多租户支持来实现。 Spring提供租赁,以防您有不同的业务环境来实现特定的组件或行为。
答案 2 :(得分:2)
听起来用户可以选择对象的1..N图形,而您只想加载用户在运行时选择的图形。如果图形在设计时已知,但用户只选择他们想要的图形,那么它听起来就像你拥有的是一堆ApplicationContexts而你只想加载用户在运行时选择的一个ApplicationContext。那么为什么不定义ApplicationContexts集合,然后在运行时实例化正确的ApplicationContexts集合。由于Spring支持Java Config,因此可以将这些配置定义为Java类,这样就可以获得继承并避免剪切/粘贴任何代码。