#java #spring
#java #spring
Вопрос:
Я ломал голову над этим, и я просто не могу понять, что не так.
У меня есть приложение Spring, которое использует ApplicationContext.getBean() для извлечения 2 похожих классов. Я получаю неправильный класс экземпляра из поиска компонента.
Вот класс ApplicationContext:
public class DomainRegistryCab {
private static ApplicationContext applicationContext;
private static ApplicationContext createApplicationContext() {
return new AnnotationConfigApplicationContext( CaBridgeDomainServiceConfig.class );
}
public static CertificateProductApplicationService certificateProductAppService() {
var service = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
applicationContext().getAutowireCapableBeanFactory(),
CertificateProductApplicationService.class,
CaBridgeDomainServiceConfig.CERTIFICATE_PRODUCT_APP_SERVICE);
// var service = applicationContext().getBean(
// CaBridgeDomainServiceConfig.CERTIFICATE_PRODUCT_APP_SERVICE,
// CertificateProductApplicationService.class);
// var service = applicationContext().getBean(CertificateProductApplicationService.class);
validateDataSourceIs(DataSource.ProductDataStore, service.dataSource());
return service;
}
public static CertificateProgramApplicationService certificateProgramAppService() {
var service = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
applicationContext().getAutowireCapableBeanFactory(),
CertificateProgramApplicationService.class,
CaBridgeDomainServiceConfig.CERTIFICATE_PROGRAM_APP_SERVICE);
// var service = applicationContext().getBean(
// CaBridgeDomainServiceConfig.CERTIFICATE_PROGRAM_APP_SERVICE,
// CertificateProgramApplicationService.class);
// service = applicationContext().getBean(CertificateProgramApplicationService.class);
validateDataSourceIs(DataSource.ProgramDataStore, service.dataSource());
return service;
}
Вот CaBridgeDomainServiceConfig:
@Configuration
@ComponentScan(basePackageClasses = { HibernateConfigurationMarker.class })
public class CaBridgeDomainServiceConfig {
public static final String CERTIFICATE_PRODUCT_APP_SERVICE = "certificateProductAppService";
public static final String CERTIFICATE_PROGRAM_APP_SERVICE = "certificateProgramAppService";
@Bean(name= CERTIFICATE_PRODUCT_APP_SERVICE)
public CertificateProductApplicationService certificateProductAppService() {
return new CertificateProductApplicationServiceCabImpl();
}
@Bean(name= CERTIFICATE_PROGRAM_APP_SERVICE)
public CertificateProgramApplicationService certificateProgramAppService() {
return new CertificateProgramApplicationServiceCabImpl();
}
}
public interface CertificateProductApplicationService extends CertificateApplicationService {
}
public interface CertificateProductApplicationService extends CertificateApplicationService {
}
public interface CertificateApplicationService {
}
Используя вышеуказанные классы, если я вызываю DomainRegistryCab.certificateProductAppService() Я получаю экземпляр CertificateProgramApplicationService, а не CertificateProductApplicationService .
Я получаю аналогичные результаты, если использую этот метод:
public static CertificateProductApplicationService certificateProductAppService() {
var service = applicationContext().getBean(
CaBridgeDomainServiceConfig.CERTIFICATE_PRODUCT_APP_SERVICE,
CertificateProductApplicationService.class);
validateDataSourceIs(DataSource.ProductDataStore, service.dataSource());
return service;
}
Я также пытался заставить методы @Bean возвращать классы реализации и ApplicationContext().getBean() запрашивать классы реализации вместо интерфейсов:
public class DomainRegistryCab {
private static ApplicationContext applicationContext;
private static ApplicationContext createApplicationContext() {
return new AnnotationConfigApplicationContext( CaBridgeDomainServiceConfig.class );
}
public static CertificateProductApplicationService certificateProductAppService() {
var service = applicationContext().getBean(CertificateProductApplicationServiceCabImpl.class);
validateDataSourceIs(DataSource.ProductDataStore, service.dataSource());
return service;
}
public static CertificateProgramApplicationService certificateProgramAppService() {
var service = applicationContext().getBean(CertificateProgramApplicationServiceCabImpl.class);
validateDataSourceIs(DataSource.ProgramDataStore, service.dataSource());
return service;
}
public static ApplicationContext applicationContext() {
if (applicationContext == null)
applicationContext = createApplicationContext();
return applicationContext;
}
}
@ComponentScan(basePackageClasses = { HibernateConfigurationMarker.class })
public class CaBridgeDomainServiceConfig {
@Bean(name= CERTIFICATE_PRODUCT_APP_SERVICE)
public CertificateProductApplicationServiceCabImpl certificateProductAppService() {
return new CertificateProductApplicationServiceCabImpl();
}
@Bean(name= CERTIFICATE_PROGRAM_APP_SERVICE)
public CertificateProgramApplicationServiceCabImpl certificateProgramAppService() {
return new CertificateProgramApplicationServiceCabImpl();
}
}
Этот код приводит к тому, что spring вообще не находит классы реализации:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cmb.cabridge.application.cert.CertificateProductApplicationServiceCabImpl' available
Комментарии:
1. Я не вижу никаких проблем с вашим первым подходом. Можете ли вы попробовать отладку, распечатав все свои
spring-beans
после создания контекста приложения, чтобы проверить, какие компоненты присутствуют в контексте? См . baeldung.com/spring-show-all-beans2. Да, я включил ведение журнала spring Framework для ОТЛАДКИ, и это показывает, что он находит оба компонента. Я также напечатал ApplicationContext.getbeandefinitionname(), и он также показывает оба компонента.
3. Можете ли вы воспроизвести его на github.com ? Какую версию spring вы используете?
4. К сожалению, мы не можем опубликовать его на github как собственное приложение. Использование springframework 5.16.RELEASE.
5. Только что обновлено до springframework 5.2.11.RELEASE и spring boot 2.3.6.RELEASE и все еще имеет ту же проблему.
Ответ №1:
В конце концов я смог заставить вещи работать, используя ApplicationContext().getBean(«beanName», CertificateProductApplicationService.class ). Проблема была глубже в моем коде в классе CertificateProductApplicationServiceCabImpl, который использовал и вернул неправильный источник данных.