【问题标题】:Spring ApplicationContext.getBean returns wrong classSpring ApplicationContext.getBean 返回错误的类
【发布时间】:2020-11-16 19:39:16
【问题描述】:

我一直在努力解决这个问题,但我就是不知道出了什么问题。

我有一个 Spring 应用程序,它使用 ApplicationContext.getBean() 来检索 2 个类似的类。我从 bean 查找中得到了错误的实例类。

这是 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

【问题讨论】:

  • 我认为您的第一种方法没有任何问题。您可以在创建应用程序上下文后通过打印所有spring-beans 来尝试调试以验证上下文中存在哪些bean?见baeldung.com/spring-show-all-beans
  • 是的,我已启用 Spring 框架日志记录到 DEBUG,它显示它找到了两个 bean。我还打印了 ApplicationContext.getBeanDefinitionNames() 它还显示了两个 bean。
  • 你能在 github.com 上重现它吗?你用的是什么春季版本?
  • 抱歉,我们不能将它作为专有应用程序发布到 github 上。使用springframework 5.16.RELEASE.
  • 刚刚更新到 springframework 5.2.11.RELEASE 和 spring boot 2.3.6.RELEASE 仍然有同样的问题。

标签: java spring


【解决方案1】:

我最终能够使用 applicationContext().getBean("beanName", CertificateProductApplicationService.class) 让事情正常工作。问题在我的 CertificateProductApplicationServiceCabImpl 类中的代码中更深层次,它使用并返回了错误的数据源。

【讨论】:

    猜你喜欢
    • 2020-11-14
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    相关资源
    最近更新 更多