使用Spring的Java Config,我需要使用只能在运行时获得的构造函数参数来获取/实例化作用域原型的bean。考虑以下代码示例(为简便起见,已简化):
@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类的定义如下:
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; } }
注意事项name是final:它只能通过构造函数来提供,并保证不变性。其他依赖关系是Thing类的特定于实现的依赖关系,不应知道(紧密耦合到)请求处理程序实现。
这段代码与Spring XML配置完美配合,例如:
<bean id="thing", class="com.whatever.Thing" scope="prototype"> <!-- other post-instantiation properties omitted --> </bean>
如何使用Java配置实现同一目的?以下内容在Spring 3.x中不起作用:
@Bean @Scope("prototype") public Thing thing(String name) { return new Thing(name); }
现在,我可以创建一个工厂,例如:
public interface ThingFactory { public Thing createThing(String name); }
但这打败了使用Spring替换ServiceLocator和Factory设计模式的整个观点,这对于该用例而言是理想的选择。
如果Spring Java Config可以做到这一点,我将能够避免:
相对于琐碎的事情,Spring已经通过XML配置支持了很多工作(相对而言)。
在@Configuration课堂上,@Bean像这样的方法
@Configuration
@Bean
用于注册bean定义并提供创建bean的工厂。它定义的bean仅在请求时使用直接或通过扫描确定的参数实例化ApplicationContext。
ApplicationContext
对于prototypebean,每次都会创建一个新对象,因此@Bean也会执行相应的方法。
prototypebean
你可以ApplicationContext通过的BeanFactory#getBean(String name, Object... args)方法检索Bean,该方法指出
BeanFactory#getBean(String name, Object... args)
Bean
允许指定显式构造函数自变量/工厂方法自变量,覆盖Bean定义中指定的默认自变量(如果有)。
参数:
如果使用静态工厂方法的显式参数创建原型,则使用args参数。在任何其他情况下,使用非null参数值都是无效的。
换句话说,对于此prototype作用域的bean,你将提供将要使用的参数,而不是在bean类的构造函数中,而是在@Bean方法调用中。
prototype
对于Spring 4+版本至少是这样。