如何以编程方式向Spring上下文中添加@Bean定义?

4

通常,我会使用@Bean定义将对象添加到Spring上下文中:

@Autowired
private SpringBus bus;

//register a singleton
@Bean
public WebservicePort getPort() {
    //new port()
    //initialize
    //configure
    //return port;
}

但现在我需要更深入地掌握这个过程,尤其是我想动态地创建bean名称,以便注册bean。
我尝试过:
@Service
public class MyPortRegistrar implements BeanDefinitionRegistryPostProcessor {

        @Autowired
        private SpringBus bus;

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println(bus); //prints null

            //create and configure port with the SpringBus
            Port port = new WebservicePort(bus); // -> throws NullPointerException
            beanFactory.autowireBean(port);
            beanFactory.initializeBean(port, "myDynamicPortName");  
        }
}

但是这会抛出NPE,因为Autowired依赖项在此处尚未初始化!那么,我该如何以编程方式添加这些bean呢?

你的问题还不够清楚...你能否再详细解释一下吗? - Abhinab Kanrar
有什么不清楚的地方吗?我想在Spring上下文中手动注册bean,并自己创建bean名称。问题是当调用postProcessBeanFactory()时,SpringBus仍然为空,因此会抛出NPE。可能在调用此方法时,@Autowired依赖项尚未被处理。因此,我想知道在所有自动装配的依赖项都被处理后,如何注册自己的bean。 - membersound
3个回答

4

在此之前应该放置这个:

beanFactory.autowireBean(port);

但是,如果你想要初始化一个bean,我认为你想要创建一个单例(我这么说是因为在例子中,你使用了@Bean注解):

beanFactory.initializeBean(port, "myDynamicPortName");  

替代单例模式:

beanFactory.registerSingleton("myDynamicPortName", port);

我尝试使用@AutowiredBean,然后是initializeBean。仍然收到NPE,指向SpringBus为空。 - membersound
端口在哪里声明? - Michael
请看一下我的更新。我是在尝试将端口与BeanFactory连接之前创建的。 - membersound

4
你应该自动装配bean工厂,并使用@PostConstruct注册你的bean。这样,你就可以保证所有依赖项都被注入了(bean工厂由容器注入,不需要设置)。
@Service
public class MyPortRegistrar {

    @Autowired
    private ConfigurableBeanFactory beanFactory;

    @Autowired
    private SpringBus bus;

    @PostConstruct
    public void createPort() {
        Port port = new WebservicePort(bus);
        beanFactory.registerSingleton("myDynamicPortName", port);
    }
}

1

除了 Khalid 的答案(我认为需要一些额外的依赖和配置),另一个选择是实现 InitializingBean 接口:

@Service
public class MyPortRegistrar implements InitializingBean {

    @Autowired
    private SpringBus bus;

    @Autowired
    private ConfigurableBeanFactory beanFactory;

    @Override
    public void afterPropertiesSet() throws Exception
        System.out.println(bus); //prints null

        //create and configure port with the SpringBus
        Port port = new WebservicePort(bus); // -> throws NullPointerException
        beanFactory.autowireBean(port);
        beanFactory.initializeBean(port, "myDynamicPortName");  
    }
}

我尝试过这个,但是 cxt.getBean("myDynamicPortName") 找不到 bean,所以可能这种方式行不通。 - membersound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接