[英]Is it possible to register an object dynamically created by myself in runtime as a spring bean?
I need to use Spring AOP facility and would not like to make AspectJ integration in order to intercept a method call to an object which is not initially a spring bean. 我需要使用Spring AOP工具,并且不想进行AspectJ集成以拦截对最初不是spring bean的对象的方法调用。 The object is going to be created dynamically in runtime . 该对象将在运行时动态创建。 It's not possible for me to add a bean definition into ApplicationContext
configuration file. 我不可能在ApplicationContext
配置文件中添加bean定义。 So does spring provide such a facility? 那么春天提供这样的设施吗?
Yes, it's possible. 是的,这是可能的。 You could create a prototype scoped bean with @Bean
and @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
in a @Configuration
bean, which would act as a factory: 您可以在@Configuration
bean中使用@Bean
和@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
创建一个原型范围的bean,它将充当工厂:
@Configuration
public class Factory {
public static class A {
private final int x;
public A(int x) {
this.x = x;
}
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Autowired
public A getA(int arg) {
try {
return A.class.getConstructor(int.class).newInstance(arg);
} catch (Exception e) {
throw new BeanCreationException("A" + arg, "Could not create instance of bean A", e);
}
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public int getArg() {
return (int) (Math.random() * 2 + 1);
}
@PostConstruct
public void test() {
int r1 = this.getArg();
A a1 = this.getA(r1);
System.out.println("a1.x = " + a1.x); // 1 or 2
int r2 = this.getArg();
A a2 = this.getA(r2);
System.out.println("a2.x = " + a2.x); // 2 or 1, different to a1.x
}
}
In method getA()
, I could have created an instance of the A
bean just with new A(arg)
, however I created it dynamically, so that it's closer to your use case. 在方法getA()
,我可以使用new A(arg)
创建A
bean的实例,但是我动态创建它,以便它更接近您的用例。
Note that from Spring 4.x version onwards, you can use @Autowired
to autowire the parameters of the bean to be returned by a @Bean
method, meaning that those parameters can be other beans, even of primitive types. 请注意,从Spring 4.x版本开始,您可以使用@Autowired
来自动装配由@Bean
方法返回的bean的参数,这意味着这些参数可以是其他bean,甚至是原始类型。 That's why I made the argument of the A
bean to also be a prototype scoped bean. 这就是为什么我让A
bean的论点也成为原型范围的bean。
Then in the @PostConstruct
method (which I'm using as a test), I get two instances of the int
argument and two instances of the A
bean, and assign each one of them to each instance of A
. 然后在@PostConstruct
方法(我用作测试)中,我获得了int
参数的两个实例和A
bean的两个实例,并将它们中的每一个分配给A
每个实例。
If I hadn't used the @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
annotation, both getArg()
and getA(arg)
@Bean
methods would have returned the same instance when invoked for the second time, as Spring's default scope for beans is ConfigurableBeanFactory.SCOPE_SINGLETON
. 如果我没有使用@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
注释,则getArg()
和getA(arg)
@Bean
方法在第二次调用时都会返回相同的实例,因为Spring的bean默认范围是ConfigurableBeanFactory.SCOPE_SINGLETON
。 If this is the behavior you expect, just remove the @Scope
annotations. 如果这是您期望的行为,只需删除@Scope
注释即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.