简体   繁体   中英

Spring ApplicationContext.getBean returns wrong class

I've been beating my head over this and I just can't figure out what's wrong.

I have a Spring app which uses ApplicationContext.getBean() to retrieve 2 similar classes. I'm getting the wrong instance class from the bean lookup.

Here's ApplicationContext class:

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;
    }

Here is 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 {
}

Using the above classes if I call DomainRegistryCab.certificateProductAppService() I get an instance of CertificateProgramApplicationService not CertificateProductApplicationService.

I get similar results if I use this method:

public static CertificateProductApplicationService certificateProductAppService() {
    var service = applicationContext().getBean(
        CaBridgeDomainServiceConfig.CERTIFICATE_PRODUCT_APP_SERVICE,
        CertificateProductApplicationService.class);
    validateDataSourceIs(DataSource.ProductDataStore, service.dataSource());
    return service;
}

I've also tried having the @Bean methods return the implementation classes and the ApplicationContext().getBean() to request the implementation classes instead of the interfaces:

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();
    }
}

This code results in spring not finding the implementation classes at all:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cmb.cabridge.application.cert.CertificateProductApplicationServiceCabImpl' available

I was eventually able to get things to work using the applicationContext().getBean("beanName", CertificateProductApplicationService.class). The problem was deeper in my code in the CertificateProductApplicationServiceCabImpl class which used and returned the wrong datasource.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM