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

Java 从命令行创建带参数bean的惯用方法?,java,spring,javabeans,Java,Spring,Javabeans,例如,在我的spring应用程序中,我需要几个DBWorker bean: @Component @Scope("prototype") class DBWorker { @Autowired JdbcTemplate templ; @Autowired SomeOtherDependency dep; public void init() { // use jdbcTemplate to pull some

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

    @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() { .... }

    }
所以基本上我有一个类DBWorker,它需要一系列依赖项,比如jdbctemplate。让Spring注入这些依赖项很方便,所以我将这些依赖项标记为@Autowired。在我的应用程序中,我需要3个位于不同位置的dbworker,它们对jdbcTemplate和其他依赖项具有相同的依赖关系。但是它们每个都有不同的maxNumberOfRowsToPull,它们都是由命令行args设置的

我需要在DBWorker上执行的逻辑步骤包括: 实例化3个工人 对每个工作进程调用init() 对每个工作进程调用run()

因为maxNumberOfRowsToPull来自命令行(不是固定的),所以我不能将它放在spring config.xml中或使用@Value注释,即使我可以在config中使用${system.property.name},这对于3个工作者来说是不同的,我必须设置系统属性3次才能间接地将其设置为setMaxNumberOfRowsToPull(),这很难看。 所以我必须直接调用setMaxNumberOfRowsToPull()。然后在调用之前,工作进程的“状态”是不完整的,所以在显式调用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设置为system属性,并让Spring处理它。因此,每个workerbean从Spring出来时都带有一些“默认”属性设置(由命令行给出),我必须显式地调用一些属性设置来更改默认值。这听起来有点可疑,因为创建后的一些bean处于“错误”状态。我宁愿让每个bean在概念上被创建时都是正确的

我还必须手动调用这个init(),因为我必须等待手动调用属性设置。假设init()应该是springbean 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(字符串名、对象…参数)

我没有试过,但这应该可以帮你

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

您可能会考虑使用JavaCon FIG来实例化和配置bean,将值注入配置类。javaconfig看起来确实是一个不错的选择,因为它提供了更多的灵活性。但是JavaConfig中的@Bean如何访问命令行参数呢?到目前为止,我所看到的唯一可以在链中传递值的方法是系统属性,但如果我们这样做,基本上在应用程序上,您将最终调用类似的步骤(尽管为我们保存init()调用)init(args[0],args[1])将起作用。我只是有点保留,因为这些属性是标准的getter和setter,代表bean的“属性”,而init()有点暗示“运行某个一次性操作”。我编辑了我的答案,并添加了一些我认为会帮助您请求的内容。。这东西应该有用。使用BeanFactoryah代替applicationContext!谢谢这正是我想要的。为什么我从来不知道getBean()的args形式。。。。