Я интегрирую JTA (Atomikos) с Spring boot + hibernate.Я хочу обработать переменную номер источника данных.Ниже приведена моя часть кода конфигурации.
@Configuration
@ConditionalOnProperty(prefix = "spring.jta.atomikos", name = "enableAtomikosHibernateJpaConfiguration")
@EnableConfigurationProperties(JpaProperties.class)
@Order(Ordered.LOWEST_PRECEDENCE)
public class AtomikosHibernateJpaConfiguration implements InitializingBean{
private static final Log logger = LogFactory.getLog(AtomikosHibernateJpaConfiguration.class);
private BeanDefinitionRegistry beanRegistry;
@Autowired
LocalContainEMFFactory lcEEMFF;
@Autowired
BeanDefinitionRegistryProvider beanDefinitionRegistryProvider;
@Autowired
List<DataSource> dataSources;
@Autowired
List<ScanPackageProperties> scanPackageProperties;
@Autowired
JpaProperties properties;
@Autowired
private JtaTransactionManager jtaTransactionManager;
public AtomikosHibernateJpaConfiguration() {
}
@Override
public void afterPropertiesSet() throws Exception {
beanRegistry = beanDefinitionRegistryProvider.getBeanDefReg();
int i = 0;
for(DataSource ds : dataSources) {
String beanName = "entityManagerFactory" + i;
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(AbstractEntityManagerFactoryBean.class);
builder.setFactoryMethodOnBean("createLocalContainEM", "LocalContainEMFFactory");
builder.addConstructorArgValue(ds);
builder.addConstructorArgValue(properties);
builder.addConstructorArgValue(scanPackageProperties.get(i).getPac());
builder.addConstructorArgValue(getJtaTransactionManager());
builder.setAutowireMode(3);
beanRegistry.registerBeanDefinition(beanName, builder.getBeanDefinition());
//BeanDefinition newBeanDef = beanRegistry.getBeanDefinition(beanName);
//((ConfigurableListableBeanFactory) beanRegistry).initializeBean(newBeanDef, beanName);
//((ConfigurableListableBeanFactory) beanRegistry).autowireBean(newBeanDef);
i++;
}
}
// @Bean
// public LocalContainerEntityManagerFactoryBean entityManagerFactory0(@Qualifier("dataSourceOne") DataSource dataSource
// , JpaProperties properties
// ) {
// EntityManagerFactoryBuilder factoryBuilder = new EntityManagerFactoryBuilder(
// new HibernateJpaVendorAdapter(), new HashMap(),
// null);
//
// Map<String, Object> vendorProperties = lcEEMFF.getVendorProperties(properties);
// lcEEMFF.customizeVendorProperties(vendorProperties, jtaTransactionManager);
// return factoryBuilder.dataSource(dataSource).packages("sample.atomikos")
// .properties(vendorProperties)
// .jta(true).build();
//
// }
// @Bean
// public LocalContainerEntityManagerFactoryBean entityManagerFactory1(@Qualifier("dataSourceTwo") DataSource dataSource, JpaProperties properties) {
// EntityManagerFactoryBuilder factoryBuilder = new EntityManagerFactoryBuilder(
// new HibernateJpaVendorAdapter(), new HashMap(),
// null);
//
// Map<String, Object> vendorProperties = lcEEMFF.getVendorProperties(properties);
// lcEEMFF.customizeVendorProperties(vendorProperties, jtaTransactionManager);
// return factoryBuilder.dataSource(dataSource).packages("sample.atomikos2.repo2")
// .properties(vendorProperties)
// .jta(true).build();
// }
...
Этот код приведет к ошибке с сообщением:
Ошибка создания компонента с именем 'jpaContext': неудовлетворенная зависимость, выраженная через параметр конструктора 0;Вложенное исключение - org.springframework.beans.factory.NoSuchBeanDefinitionException: нет доступного квалифицирующего компонента типа 'java.util.Set': ожидается как минимум 1 компонент, который квалифицируется как кандидат для автоматического подключения.Аннотации зависимостей: {}
Насколько я понимаю, Spring должен использовать мой динамический регистр EJB для создания EntityManager.Если я прокомментирую этот код определений динамических компонентов регистра и раскомментирую этот текущий закомментированный код (public LocalContainerEntityManagerFactoryBean entityManagerFactory0
и т. Д.), Все будет работать хорошо.Я уверен, что был вызван метод фабрики бинов (createLocalContainEM).Мне просто интересно, есть ли что-то упущенное в моем определении бина регистра?Кто-нибудь может дать какой-нибудь совет?
ссылаются на LocalContainEMFFactory и BeanDefinitionRegistryProvider:
@Component("LocalContainEMFFactory")
public class LocalContainEMFFactory{
String JTA_PLATFORM = "hibernate.transaction.jta.platform";
public LocalContainerEntityManagerFactoryBean
createLocalContainEM(DataSource dataSource
, JpaProperties properties,
String scanPackage,
JtaTransactionManager jtaTransactionManager) {
EntityManagerFactoryBuilder factoryBuilder = new EntityManagerFactoryBuilder(
new HibernateJpaVendorAdapter(), new HashMap(),
null);
Map<String, Object> vendorProperties = getVendorProperties(properties);
customizeVendorProperties(vendorProperties, jtaTransactionManager);
return factoryBuilder.dataSource(dataSource).packages(scanPackage)
.properties(vendorProperties)
.jta(true).build();
}
...
}
@Component
public class BeanDefinitionRegistryProvider implements BeanFactoryPostProcessor{
BeanDefinitionRegistry beanDefReg;
public BeanDefinitionRegistry getBeanDefReg() {
return beanDefReg;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanDefReg = (BeanDefinitionRegistry) beanFactory;
}
}
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Autowired
BeanDefinitionRegistryProvider beanDefinitionRegistryProvider;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextProvider.applicationContext = applicationContext;
BeanDefinitionRegistry beanRegistry = beanDefinitionRegistryProvider.getBeanDefReg();
for(int i = 0; i<2; i++) {
String beanName = "entityManagerFactory" + i;
Object newBeanDef = applicationContext.getBean(beanName);
// ((ConfigurableListableBeanFactory) beanRegistry).initializeBean(newBeanDef, beanName);
((ConfigurableListableBeanFactory) beanRegistry).autowireBean(newBeanDef);
}
}
public static final ApplicationContext getApplicationContext(){
return applicationContext;
}
}