是否可以在运行时将自己动态创建的对象注册为spring bean?

时间:2015-03-16 10:37:00

标签: java spring aop

我需要使用Spring AOP工具,并且不想进行AspectJ集成以拦截对最初不是spring bean的对象的方法调用。该对象将在运行时动态创建。我无法将bean定义添加到ApplicationContext配置文件中。那么春天提供这样的设施吗?

1 个答案:

答案 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注释。