弹簧动态注入,工厂式花纹

依赖性注射的延续,延迟的注射实践。我有主类:

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()。或者像这样称呼它,从某个方法 - 这再次看起来很糟糕,迫使方法负责实例化对象图。

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

enter image description here

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

谢谢。


答案 1

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

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

编辑:

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

当您配置类时,将查找方法分配给其成员 - 每当您需要Bean的新实例时,都会调用它。MainListList

祝你好运!


答案 2

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

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

顺便说一句,以下选项可以在您的案例中使用:感谢BeanFactoryAware接口和scope=“prototype”的使用,您可以通过调用该示例或从另一个问题生成Bean:按需创建BeanBeanFactorygetBean()

如果您要准备的豆子数量有限,另一种选择是使用仿制药豆创建,就像嘲笑缺乏豆子一样

现在考虑一下,Spring从不在其上下文中垃圾收集豆类。因此,创建Spring Bean来保存业务数据对于内存消耗是有风险的。

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


推荐