从 Spring 3 升级到 Spring 5 - 现在自动装配错误

Posted

技术标签:

【中文标题】从 Spring 3 升级到 Spring 5 - 现在自动装配错误【英文标题】:Upgraded from Spring 3 to Spring 5 - and now errors with autowiring 【发布时间】:2019-08-23 15:57:06 【问题描述】:

有一个升级 Java、weblogic 的项目,它最终在我们的一个 web 应用程序中出现。 曾经是 java 6、weblogic 10 和 spring 3。 迁移到 java 8、weblogic 12 和 spring 5。

在编译时经历了很多依赖地狱并且不得不围绕一些贬值的 spring 类进行重构之后,我已经构建了它。

这是真正的问题开始的时候。

部署应用时出现以下异常。

' 可用:预计至少有 1 个 bean自动接线候选人。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=healthPlanCheckoutFunnelStateHolderMapper)。

org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“findAPlanCheckoutController”的bean时出错:通过字段“funnelStateHolderMapper”表示的依赖关系不满足;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有可用的“com.vhi.web.common.mappers.FunnelStateHolderMapper”类型的合格 bean:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=healthPlanCheckoutFunnelStateHolderMapper) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596) 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1395) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:400) 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291) 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103) 在 weblogic.servlet.internal.EventsManager$FireContextListenerAction.run(EventsManager.java:705) 在 weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326) 在 weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197) 在 weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203) 在 weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71) 在 weblogic.servlet.internal.EventsManager.executeContextListener(EventsManager.java:251) 在 weblogic.servlet.internal.EventsManager.notifyContextCreatedEvent(EventsManager.java:204) 在 weblogic.servlet.internal.EventsManager.notifyContextCreatedEvent(EventsManager.java:189) 在 weblogic.servlet.internal.WebAppServletContext.preloadResources(WebAppServletContext.java:1921) 在 weblogic.servlet.internal.WebAppServletContext.start(WebAppServletContext.java:3101) 在 weblogic.servlet.internal.WebAppModule.startContexts(WebAppModule.java:1843) 在 weblogic.servlet.internal.WebAppModule.start(WebAppModule.java:884) 在 weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:360) 在 weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:356) 在 weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45) 在 weblogic.application.internal.ExtensibleModuleWrapper.start(ExtensibleModuleWrapper.java:138) 在 weblogic.application.internal.flow.ModuleListenerInvoker.start(ModuleListenerInvoker.java:124) 在 weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:233) 在 weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:228) 在 weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45) 在 weblogic.application.internal.flow.ModuleStateDriver.start(ModuleStateDriver.java:78) 在 weblogic.application.internal.flow.StartModulesFlow.activate(StartModulesFlow.java:52) 在 weblogic.application.internal.BaseDeployment$2.next(BaseDeployment.java:752) 在 weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45) 在 weblogic.application.internal.BaseDeployment.activate(BaseDeployment.java:262) 在 weblogic.application.internal.EarDeployment.activate(EarDeployment.java:66) 在 weblogic.application.internal.DeploymentStateChecker.activate(DeploymentStateChecker.java:165) 在 weblogic.deploy.internal.targetserver.AppContainerInvoker.activate(AppContainerInvoker.java:90) 在 weblogic.deploy.internal.targetserver.operations.AbstractOperation.activate(AbstractOperation.java:631) 在 weblogic.deploy.internal.targetserver.operations.ActivateOperation.activateDeployment(ActivateOperation.java:171) 在 weblogic.deploy.internal.targetserver.operations.ActivateOperation.doCommit(ActivateOperation.java:121) 在 weblogic.deploy.internal.targetserver.operations.AbstractOperation.commit(AbstractOperation.java:348) 在 weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentCommit(DeploymentManager.java:907) 在 weblogic.deploy.internal.targetserver.DeploymentManager.activateDeploymentList(DeploymentManager.java:1468) 在 weblogic.deploy.internal.targetserver.DeploymentManager.handleCommit(DeploymentManager.java:459) 在 weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.commit(DeploymentServiceDispatcher.java:181) 在 weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doCommitCallback(DeploymentReceiverCallbackDeliverer.java:217) 在 weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access 100 美元(DeploymentReceiverCallbackDeliverer.java:14) 在 weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$2.run(DeploymentReceiverCallbackDeliverer.java:69) 在 weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:678) 在 weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:352) 在 weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:337) 在 weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:57) 在 weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41) 在 weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:652) 在 weblogic.work.ExecuteThread.execute(ExecuteThread.java:420) 在 weblogic.work.ExecuteThread.run(ExecuteThread.java:360) 原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有可用的“com.vhi.web.common.mappers.FunnelStateHolderMapper”类型的合格bean:预计至少有1个有资格作为自动装配候选者的bean。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=healthPlanCheckoutFunnelStateHolderMapper) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1654) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1213) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1395) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:400) 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291) 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103) 在 weblogic.servlet.internal.EventsManager$FireContextListenerAction.run(EventsManager.java:705) 在 weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326) 在 weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197) 在 weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203) 在 weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71) 在 weblogic.servlet.internal.EventsManager.executeContextListener(EventsManager.java:251) 在 weblogic.servlet.internal.EventsManager.notifyContextCreatedEvent(EventsManager.java:204) 在 weblogic.servlet.internal.EventsManager.notifyContextCreatedEvent(EventsManager.java:189) 在 weblogic.servlet.internal.WebAppServletContext.preloadResources(WebAppServletContext.java:1921) 在 weblogic.servlet.internal.WebAppServletContext.start(WebAppServletContext.java:3101) 在 weblogic.servlet.internal.WebAppModule.startContexts(WebAppModule.java:1843) 在 weblogic.servlet.internal.WebAppModule.start(WebAppModule.java:884) 在 weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:360) 在 weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:356) 在 weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45) 在 weblogic.application.internal.ExtensibleModuleWrapper.start(ExtensibleModuleWrapper.java:138) 在 weblogic.application.internal.flow.ModuleListenerInvoker.start(ModuleListenerInvoker.java:124) 在 weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:233) 在 weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:228) 在 weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45) 在 weblogic.application.internal.flow.ModuleStateDriver.start(ModuleStateDriver.java:78) 在 weblogic.application.internal.flow.StartModulesFlow.activate(StartModulesFlow.java:52) 在 weblogic.application.internal.BaseDeployment$2.next(BaseDeployment.java:752) 在 weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45) 在 weblogic.application.internal.BaseDeployment.activate(BaseDeployment.java:262) 在 weblogic.application.internal.EarDeployment.activate(EarDeployment.java:66) 在 weblogic.application.internal.DeploymentStateChecker.activate(DeploymentStateChecker.java:165) 在 weblogic.deploy.internal.targetserver.AppContainerInvoker.activate(AppContainerInvoker.java:90) 在 weblogic.deploy.internal.targetserver.operations.AbstractOperation.activate(AbstractOperation.java:631) 在 weblogic.deploy.internal.targetserver.operations.ActivateOperation.activateDeployment(ActivateOperation.java:171) 在 weblogic.deploy.internal.targetserver.operations.ActivateOperation.doCommit(ActivateOperation.java:121) 在 weblogic.deploy.internal.targetserver.operations.AbstractOperation.commit(AbstractOperation.java:348) 在 weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentCommit(DeploymentManager.java:907) 在 weblogic.deploy.internal.targetserver.DeploymentManager.activateDeploymentList(DeploymentManager.java:1468) 在 weblogic.deploy.internal.targetserver.DeploymentManager.handleCommit(DeploymentManager.java:459) 在 weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.commit(DeploymentServiceDispatcher.java:181) 在 weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doCommitCallback(DeploymentReceiverCallbackDeliverer.java:217) 在 weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access 100 美元(DeploymentReceiverCallbackDeliverer.java:14) 在 weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$2.run(DeploymentReceiverCallbackDeliverer.java:69) 在 weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:678) 在 weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:352) 在 weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:337) 在 weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:57) 在 weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41) 在 weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:652) 在 weblogic.work.ExecuteThread.execute(ExecuteThread.java:420) 在 weblogic.work.ExecuteThread.run(ExecuteThread.java:360)

组件是:

@Component
@Qualifier("healthPlanCheckoutFunnelStateHolderMapper")
public class HealthPlanCheckoutFunnelStateHolderMapper extends CommonHealthCheckoutFunnelStateHolderMapper<HealthPlanCheckoutBean>

    @Override
    protected HealthPlanCheckoutBean createBean() 
        return new HealthPlanCheckoutBean();
    

并且该组件的自动装配是:

@Autowired
@Qualifier("healthPlanCheckoutFunnelStateHolderMapper")
private FunnelStateHolderMapper<HealthPlanCheckoutBean, HealthPlanFunnelStateHolder> funnelStateHolderMapper;

FunnelStateHolderMapper 接口

/**
 * Interface defines methods for mapping to and from a @link FunnelStateHolder. This is the top level mapper that
 * should be used by each controller for handling GET and POST requests. The implementation may delegate to other
 * underlying mappers but this should always be the interface to which the controller talks.
 */
public interface FunnelStateHolderMapper<B, F extends FunnelStateHolder> 

    B toScreenBean(F funnelStateHolder);

    F fromScreenBean(F funnelStateHolder, B screenBean);

在包含此代码所在包的配置中存在组件扫描。

这在 spring 3 上运行良好,但自从更改为 spring 5 后,这个问题就出现了。 我想我必须做一些重构才能让它编译导致了这个问题,但我不这么认为。上述代码所在的文件均未更新。

到目前为止,我还不需要更新任何 spring 配置。 spring 3 和 spring 5 搜索组件的方式有区别吗?

【问题讨论】:

尝试从 HealthPlanCheckoutFunnelStateHolderMapper 类中删除 @Qualifier("healthPlanCheckoutFunnelStateHolderMapper") 【参考方案1】:

领域

private FunnelStateHolderMapper<...> funnelStateHolderMapper;

@Component/@Qualifier注解类的类型不同

HealthPlanCheckoutFunnelStateHolderMapper

您不能指望 Spring @Autowire 会引发编译/运行时错误


如果HealthPlanCheckoutFunnelStateHolderMapper 是层次结构的一部分,请表明这一点。

【讨论】:

我对这个应用程序不是很熟悉。在此之前我并没有真正研究过它。 HealthPlanCheckoutFunnelStateHolderMapper 确实扩展了一个在它下面有 3 个抽象级别的类,我完全被它抛弃了——我不明白复杂性的必要性。由于指南,我认为我不能放入整个文件? @Kevin 您是否修改了此代码/类的其他部分?你在 Spring 3 中使用过 XML 吗? @Kevin你能把CommonHealthCheckoutFunnelStateHolderMapper的签名贴出来吗? @Kevin anway,我认为这与类型擦除有关。你的层次太深了。 public abstract class CommonHealthCheckoutFunnelStateHolderMapper&lt;B extends CommonHealthCheckoutBean&gt; extends AbstractCheckoutBeanMapperTemplate&lt;PolicyHolderDetailsBean, AdditionalPersonBean, B, CommonHealthFunnelStateHolder&gt;

以上是关于从 Spring 3 升级到 Spring 5 - 现在自动装配错误的主要内容,如果未能解决你的问题,请参考以下文章

从 Spring Boot Starter 1.3.5.RELEASE 升级到 1.5.2 RELEASE 时 Spring Security 中的访问被拒绝错误

Spring Boot 从 1.5.3 升级到 1.5.4,自定义验证配置启动失败

将 Spring Cloud 版本从 Edgware 升级到 Hoxton

从 Spring 4.2 升级到 Spring 5.0.5 时预见到的问题

将 Spring Boot 2.3.5 升级到 2.4.0

从 stark-security 升级到 spring 安全插件