Spring Java Config:如何使用运行时参数创建原型范围的@Bean? [英] Spring Java Config: how do you create a prototype-scoped @Bean with runtime arguments?

查看:113
本文介绍了Spring Java Config:如何使用运行时参数创建原型范围的@Bean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Spring的Java Config,我需要使用只能在运行时获得的构造函数参数来获取/实例化原型范围的bean。请考虑以下代码示例(为简洁起见而简化):

Using Spring's Java Config, I need to acquire/instantiate a prototype-scoped bean with constructor arguments that are only obtainable at runtime. Consider the following code example (simplified for brevity):

@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
}

其中Thing类定义如下:

where the Thing class is defined as follows:

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;
    }
}

注意名称 final :它只能通过构造函数提供,并保证不变性。其他依赖项是 Thing 类的特定于实现的依赖项,并且不应该知道(紧密耦合到)请求处理程序实现。

Notice name is final: it can only be supplied via a constructor, and guarantees immutability. The other dependencies are implementation-specific dependencies of the Thing class, and shouldn't be known to (tightly coupled to) the request handler implementation.

此代码与Spring XML配置完美配合,例如:

This code works perfectly well with Spring XML config, for example:

<bean id="thing", class="com.whatever.Thing" scope="prototype">
    <!-- other post-instantiation properties omitted -->
</bean>

如何使用Java配置实现相同的功能?以下不起作用:

How do I achieve the same thing with Java config? The following does not work:

@Bean
@Scope("prototype")
public Thing thing(String name) {
    return new Thing(name);
}

现在,我可以创建工厂,例如:

Now, I could create a Factory, e.g.:

public interface ThingFactory {
    public Thing createThing(String name);
}

打败了使用Spring取代ServiceLocator的全部意义和工厂设计模式,这将是这个用例的理想选择。

But that defeats the entire point of using Spring to replace the ServiceLocator and Factory design pattern, which would be ideal for this use case.

如果Spring Java Config可以做到这一点,我将能够避免:

If Spring Java Config could do this, I would be able to avoid:


  • 定义工厂界面

  • 定义工厂实施

  • 为Factory实现编写测试

对于Spring已经通过XML配置支持的那些微不足道的工作,这是一项大量工作(相对而言)。

That's a ton of work (relatively speaking) for something so trivial that Spring already supports via XML config.

推荐答案

@Configuration 类中, @Bean 这样的方法

@Bean
@Scope("prototype")
public Thing thing(String name) {
    return new Thing(name);
}

用于注册 bean定义并提供工厂用于创建豆子。它定义的bean仅在请求时使用直接或通过扫描 ApplicationContext 确定的参数进行实例化。

is used to register a bean definition and provide the factory for creating the bean. The bean that it defines is only instantiated upon request using arguments that are determined either directly or through scanning that ApplicationContext.

对于 prototype bean,每次都会创建一个新对象,因此相应的 @Bean 方法也被执行。

In the case of a prototype bean, a new object is created every time and therefore the corresponding @Bean method is also executed.

您可以通过 ApplicationContext 中检索bean .io / spring / docs / current / javadoc-api / org / springframework / beans / factory / BeanFactory.html#getBean-java.lang.String-java.lang.Object ...-rel =noreferrer> BeanFactory#getBean(String name,Object ... args) 表示的方法

You can retrieve a bean from the ApplicationContext through its BeanFactory#getBean(String name, Object... args) method which states


允许指定显式构造函数参数/工厂方法
参数,覆盖
bean定义中指定的默认参数(如果有)。

Allows for specifying explicit constructor arguments / factory method arguments, overriding the specified default arguments (if any) in the bean definition.

参数:

args 如果使用显式参数
创建原型到静态工厂方法,则使用这些参数。在任何其他情况下使用非空args值
无效。

args arguments to use if creating a prototype using explicit arguments to a static factory method. It is invalid to use a non-null args value in any other case.

换句话说,对于此 prototype scoped bean,你提供的是将要使用的参数,不是在bean类的构造函数中,而是在 @Bean 方法调用。

In other words, for this prototype scoped bean, you are providing the arguments that will be used, not in the constructor of the bean class, but in the @Bean method invocation.

对于Spring版本4 +,这至少是正确的。

This is at least true for Spring versions 4+.

这篇关于Spring Java Config:如何使用运行时参数创建原型范围的@Bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆