从命令行创建带有参数的bean的惯用方法?

idiomatic way to create a bean with parameter from command line?

例如,在我的 spring 应用程序中,我需要几个 DBWorker Beans:

    @Component
    @Scope("prototype")
    class DBWorker {

    @Autowired
    JdbcTemplate templ;

    @Autowired
    SomeOtherDependency dep;


    public void init() {
        // use jdbcTemplate to pull some 
        // set up info from DB

   }

   public void run() {
    // pull maxNumberOfRows and print out
   }


    private int maxNumberOfRowsToPull;

    public void setMaxNumberOfRowsToPull() { .... }

    }

所以基本上我有一个 class DBWorker ,它需要一堆依赖项,例如 jdbctemplate。让Spring注入这些依赖很方便,所以我把这些依赖标记为@Autowired。在我的应用程序中,我在不同的地方需要 3 个 DBWorker,它们都对 jdbcTemplate 和 SomeOtherDependency 具有相同的依赖关系。但是它们每个都有不同的 maxNumberOfRowsToPull,它们都是由命令行参数设置的。

我需要在 DBWorker 上执行的逻辑步骤是: 实例化 3 个工人 对每个工人调用 init() 在每个 worker

上调用 运行()

因为 maxNumberOfRowsToPull 来自命令行(不固定),我不能把它放在 spring config.xml 或使用 @Value 注释,即使我可以使用 ${system.property.name} 在 config 中,这对于 3 个工作人员来说会有所不同,我必须设置 system 属性 3 次才能间接进入 setMaxNumberOfRowsToPull(),这很丑陋。 所以我必须直接调用 setMaxNumberOfRowsToPull()。然后在我调用它之前,worker 的 "state" 不完整,所以在我显式调用 setMaxNumberOfRowsToPull() 之前我不能调用 init(),所以我不能将 init() 逻辑放在构造函数中,并且也必须显式调用 init() 。另一方面,我想自动装配依赖项,所以我必须通过 spring 创建 worker(否则不会注入依赖项)。所以总的来说,我现在拥有的最好的代码是:

DBWorker worker1 = (DBWorker) context.getBean(DBWorker.class);
// now the dependencies are already injected
worker1.setMaxNumberOfRowsToPull(args[0]);
worker1.setSomeOtherProperty(args[1]);
worker1.init();
worker1.run();

// then similar sequence for worker2 etc.

丑陋的部分是,如果我要从命令行设置更多属性,我将有更多调用,如 setMaxNumberOfRowsToPull(),并且大多数工作人员共享相同的参数,只有少数需要明确更改。所以我将这些属性的@Value 设置为系统 属性,并让 Spring 处理它。所以每个 worker bean 都来自 Spring,带有一些 "default" 属性 设置,由命令行给出,我将不得不显式地调用一些 属性 设置来改变默认值。这听起来有点可疑,因为一些 bean 在创建后处于 "wrong" 状态。从概念上讲,我宁愿让每个 bean 在创建时都是正确的。

我还必须手动调用此 init(),因为我必须等待 属性 设置上的手动调用。据说 init() 应该是 spring bean initialization() 的一部分,我不需要为每个 dbworker 执行这个机械步骤。

理想情况下,我想要像

这样更干净的东西
DBWorker worker1 = context.getBean(DBWorker.class, args[0], args[1]);
// here the init() has been run inside constructor or in bean initialization()
worker1.run();
// then repeat above for worker2, worker3 ...

我想知道为这种情况组织代码的惯用且干净的方法是什么。 谢谢!

为什么不直接将变量放在 init 上?

 public void init(String numberOfRowsToPull, String otherProp) {
        // use jdbcTemplate to pull some 
        // set up info from DB
        this.numberOfRowsToPull = numberOfRowsToPull;
        this.otherProp = otherProp;
   }

主要是:

DBWorker worker1 = context.getBean(DBWorker.class);
worker1.init(args[0], args[1]);
worket1.run();

这是标准,我在很多地方都遇到过,如果您想更改默认值,它的作用与构造函数相同..

希望对您有所帮助

编辑:

BeanFactory 有一个 getBean(String name, Object... args)

我没试过,但这应该能帮到你..

getBean("dBWorker", args[0], args[1]);