我需要使用Spring AOP工具,并且不想进行AspectJ集成以拦截对最初不是spring bean的对象的方法调用。该对象将在运行时动态创建。我无法将bean定义添加到ApplicationContext
配置文件中。那么春天提供这样的设施吗?
答案 0 :(得分:3)
是的,这是可能的。您可以在@Bean
bean中创建一个原型范围的bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
和@Configuration
,它将作为工厂:
@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
}
}
在方法getA()
中,我可以使用A
创建new A(arg)
bean的实例,但我动态创建它,以便它更接近您的使用情况下。
请注意,从Spring 4.x版本开始,您可以使用@Autowired
自动装配由@Bean
方法返回的bean的参数,这意味着这些参数可以是其他bean,甚至原始类型。这就是为什么我让A
bean的参数也成为原型范围的bean。
然后在@PostConstruct
方法(我将其作为测试使用)中,我得到了int
参数的两个实例和A
bean的两个实例,以及将每一个分配给A
的每个实例。
如果我没有使用@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
注释,则getArg()
和getA(arg)
@Bean
方法在第二次调用时会返回相同的实例,因为Spring的默认范围是ConfigurableBeanFactory.SCOPE_SINGLETON
。如果这是您期望的行为,只需删除@Scope
注释。