繁体   English   中英

如何使用运行时参数创建原型范围的@Bean? 使用 getBean(String name, Object... args)?

[英]How do you create a prototype-scoped @Bean with runtime arguments? With getBean(String name, Object... args)?

如何使用运行时参数创建原型范围的@Bean? 使用getBean(String name, Object... args) 我的问题是这个问题的结果

为什么Spring IoC 文档中没有使用或提到这种方法?

这是正常的方法吗? 是否有更正确的方法来创建带有运行时参数的原型 @Bean?

如果这不是正常方法,那么您能解释一下原因吗? 注意,我需要通过构造函数而不是通过 setter 来设置我的参数。

@Autowired
private ApplicationContext appCtx;

public void onRequest(Request request) {
    //request is already validated
    String name = request.getParameter("name");
    Thing thing = appCtx.getBean(Thing.class, name);

    //System.out.println(thing.getName()); //prints name
}

——

public class Thing {

    private final String name;

    @Autowired
    private SomeComponent someComponent;

    @Autowired
    private AnotherComponent anotherComponent;

    public Thing(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

在构造函数注入方面,没有。 但是,您可以为Thing一个init方法并使用ObjectFactory

@Autowired
private ObjectFactory<Thing> thingFactory;

public void onRequest(Request request) {
    //request is already validated
    Thing thing = thingFactory.getObject();
    thing.init("name");

    //System.out.println(thing.getName()); //prints name
}

有:

@Component
@Scope("prototype")
public class Thing {

    private String name;

    @Autowired
    private SomeComponent someComponent;

    @Autowired
    private AnotherComponent anotherComponent;

    public init(String name) {
        this.name = name;
    }

}

不幸的是,该name不能是final name因为它不是通过构造函数生成的。 很想看看是否有更好的方法可以通过constructor injection

可以在bean工厂的帮助下进行:

@Configuration
public class ThingProvider {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Thing create(String name) {
        return new Thing(name);
    }

}

用法:

@Component
public class SomeBean {

    @Autowired
    private ThingProvider thingProvider;

    public void onRequest(Request request) {

        String name = request.getParameter("name");
        Thing thing = myProvider.create(name);
    }

}

通常作为反对appCtx.getBean(Thing.class, name)的参数而appCtx.getBean(Thing.class, name)是,它需要硬连接Spring特定的类。 另外,万一Thing构造函数发生变化,也没有编译时间检查。

在这种情况下,您的Thing类可能会混合构造函数依赖项和运行时参数,如下所示:

public class Thing {

    private final SomeComponent someComponent;
    private final AnotherComponent anotherComponent;

    private final String name;

    @Autowired
    public Thing(SomeComponent someComponent,
                 AnotherComponent anotherComponent,
                 String name) {
        this.someComponent = someComponent;
        this.anotherComponent = anotherComponent;
        this.name = name;
    }

    public String getName() {
        return this.name;
    } 
}

然后你可以将它们包装在配置中:

@Configuration
public class BeanConfig {

    @Autowired
    private SomeComponent someComponent;

    @Autowired
    private final AnotherComponent anotherComponent;

    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public Thing createThing(String name) {
        return new Thing(someComponent, anotherComponent, name);
    }
}

用法:

@Autowired
private BeanFactory beanFactory;

public void onRequest(Request request) {
    String name = request.getParameter("name");
    Thing thing = beanFactory.getBean(Thing.class, name);
}

它应该可以工作,但不确定这是否是一个好习惯。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM