Как я могу вставить bean в ApplicationContext перед загрузкой из файла?
У меня есть FileSystemXmlApplicationContext
, и я хотел бы, чтобы beans, определенный в XML, принимал в качестве аргумента конструктора a bean, который не объявлен в Spring
Например, я хотел бы сделать:
<bean class="some.MyClass">
<constructor-arg ref="myBean" />
</bean>
Итак, я мог представить, как это делается через что-то вроде:
Object myBean = ...
context = new FileSystemXmlApplicationContext(xmlFile);
context.addBean("myBean", myBean); //add myBean before processing
context.refresh();
За исключением того, что такого метода нет:-( Кто-нибудь знает, как я могу это достичь?
Ответы
Ответ 1
Как о программном создании пустого родительского контекста, зарегистрировав ваш объект как одноэлемент с этим контекстом BeanFactory
, используя тот факт, что getBeanFactory
возвращает реализацию SingletonBeanRegistry
.
parentContext = new ClassPathXmlApplicationContext();
parentContext.refresh(); //THIS IS REQUIRED
parentContext.getBeanFactory().registerSingleton("myBean", myBean)
Затем укажите этот контекст как родительский для вашего "реального" контекста. beans в дочернем контексте будет иметь возможность ссылаться на bean в родительском.
String[] fs = new String[] { "/path/to/myfile.xml" }
appContext = new FileSystemXmlApplicationContext(fs, parentContext);
Ответ 2
Поскольку мне удалось решить эту проблему с помощью AnnotationConfigApplicationContext, я нашел следующую альтернативу:
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("customBean", new CustomBean());
context = new AnnotationConfigApplicationContext(beanFactory);
context.register(ContextConfiguration.class);
context.refresh();
Ответ 3
Если существующий контекст нуждается в бине, который вы хотите внедрить, то все должно быть сделано немного по-другому. Подходы в других ответах не работают по следующим причинам
- Контекст не может быть обновлен, пока не будет зарегистрирован отсутствующий компонент
- refresh() вызывает уничтожение введенного компонента.
Эту проблему можно обойти, используя "постпроцессор фабрики бинов", это позволяет запускать код после загрузки контекста, но до его обновления.
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();
applicationContext.setConfigLocation("/org/example/app-context.xml");
applicationContext.getBeanFactoryPostProcessors().add(new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerSingleton("customBeanName", customBean);
}
});
applicationContext.refresh();