web-dev-qa-db-fra.com

Le haricot demandé est en cours de création: existe-t-il une référence circulaire insoluble?

j'utilise printemps 3 et j'ai deux haricots de vue:

1- Bean1:

@Component("bean1")
@Scope("view")
public class Bean1 {

@Autowired
private Bean2 bean2;

}

2- Bean2:

@Component("bean2")
@Scope("view")
public class Bean2 {

@Autowired
private Bean1 bean1;

}

la vue est une étendue personnalisée:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="view">
                    <bean class="${project.groupId}.utils.ViewScope" />
                </entry>
            </map>
        </property>
    </bean>

et voici le code pour la portée de la vue personnalisée:

public class ViewScope implements Scope {

    @SuppressWarnings("rawtypes")
    public Object get(String name, ObjectFactory objectFactory) {
        Map<String, Object> viewMap = FacesContext.getCurrentInstance()
                .getViewRoot().getViewMap();

        if (viewMap.containsKey(name)) {
            return viewMap.get(name);
        } else {
            Object object = objectFactory.getObject();
            viewMap.put(name, object);

            return object;
        }
    }

    public Object remove(String name) {
        return FacesContext.getCurrentInstance().getViewRoot().getViewMap()
                .remove(name);
    }

    public String getConversationId() {
        return null;
    }

    public void registerDestructionCallback(String name, Runnable callback) {
        // Not supported
    }

    public Object resolveContextualObject(String key) {
        return null;
    }
}

en ouvrant la page qui utilise les deux beans, j'obtiens l'exception:

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'agencyBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:252)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.Java:844)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.Java:786)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.Java:703)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:474)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.Java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:282)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.Java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.Java:329)
    at com.myapp.utils.ViewScope.get(ViewScope.Java:20)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:325)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.Java:844)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.Java:786)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.Java:703)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:474)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.Java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:282)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.Java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.Java:329)
    at com.xeno.xecamp.webManagement.utils.ViewScope.get(ViewScope.Java:20)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:325)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:190)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.Java:1075)
    at org.springframework.beans.factory.access.el.SpringBeanELResolver.getValue(SpringBeanELResolver.Java:56)
    at com.Sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.Java:176)
    at com.Sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.Java:203)
    at org.Apache.el.parser.AstIdentifier.getValue(AstIdentifier.Java:71)
    at org.Apache.el.parser.AstValue.getTarget(AstValue.Java:94)
    at org.Apache.el.parser.AstValue.invoke(AstValue.Java:244)
    at org.Apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.Java:278)
    at com.Sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.Java:105)
    at com.Sun.faces.facelets.tag.jsf.core.DeclarativeSystemEventListener.processEvent(EventHandler.Java:128)
    at javax.faces.component.UIComponent$ComponentSystemEventListenerAdapter.processEvent(UIComponent.Java:2508)
    at javax.faces.event.SystemEvent.processListener(SystemEvent.Java:106)
    at com.Sun.faces.application.ApplicationImpl.processListeners(ApplicationImpl.Java:2139)
    at com.Sun.faces.application.ApplicationImpl.invokeComponentListenersFor(ApplicationImpl.Java:2087)
    at com.Sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.Java:286)
    at com.Sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.Java:244)
    at org.springframework.faces.webflow.Jsf2FlowApplication.publishEvent(Jsf2FlowApplication.Java:94)
    at com.Sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.Java:108)
    at com.Sun.faces.lifecycle.Phase.doPhase(Phase.Java:101)
    at com.Sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.Java:139)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.Java:594)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:304)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.Java:118)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:368)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.Java:99)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.Java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.Java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.Java:60)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.Java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.Java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.Java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.Java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.Java:177)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.Java:187)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.Java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.Java:57)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:169)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:70)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.Java:684)
    at org.Apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.Java:471)
    at org.Apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.Java:402)
    at org.Apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.Java:329)
    at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.Java:110)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:368)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.Java:109)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.Java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.Java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.Java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.Java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.Java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.Java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.Java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.Java:177)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.Java:187)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.Java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.Java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:380)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:169)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.Java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:76)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:224)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:169)
    at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:472)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:168)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:100)
    at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:929)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:405)
    at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:964)
    at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:515)
    at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:304)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.Java:886)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:908)
    at Java.lang.Thread.run(Thread.Java:619)

veuillez indiquer comment résoudre cette exception.

[~ # ~] modifier [~ # ~] : j'ai essayé d'utiliser l'injection du setter comme indiqué dans la réponse ici

Comprendre l'ordre d'initialisation du contexte Spring

mais ça ne marche pas aussi.

1- Bean1:

@Component("bean1")
@Scope("view")
public class Bean1 {


private Bean2 bean2;

@Autowired
public void setBean2 (Bean2 bean2) {
    this.bean2= bean2;
}

}

2- Bean2:

@Component("bean2")
@Scope("view")
public class Bean2 {


private Bean1 bean1;

@Autowired
public void setBean1 (Bean1 bean1) {
    this.bean1= bean1;
}

}

mais cela me donne l'exception:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.myapp.beans.Bean1] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
51
Mahmoud Saleh

Spring utilise une logique particulière pour résoudre ce type de dépendances circulaires avec des haricots singleton. Mais cela ne s'appliquera pas à d'autres domaines. Il n’existe aucun moyen élégant de briser cette dépendance circulaire, mais une option maladroite pourrait être celle-ci:

@Component("bean1")
@Scope("view")
public class Bean1 {

    @Autowired
    private Bean2 bean2;

    @PostConstruct
    public void init() {
        bean2.setBean1(this);
    }
}

@Component("bean2")
@Scope("view")
public class Bean2 {

    private Bean1 bean1;

    public void setBean1(Bean1 bean1) {
        this.bean1 = bean1;
    }
}

Quoi qu’il en soit, les dépendances circulaires sont généralement le symptôme d’une mauvaise conception. Vous réfléchissez à nouveau s'il existe un meilleur moyen de définir vos dépendances de classe.

64
sinuhepop

Je pense que vous pourriez utiliser le printemps

@Paresseux

une annotation sur l'un des champs câblés automatiquement pour rompre la dépendance circulaire.

Je ne sais pas si cela fonctionne/existe dans la version de Spring mentionnée.

63
FazoM

Dans mon cas, je définissais un bean et le mettais en réseau dans le constructeur du même fichier de classe.

@SpringBootApplication
public class MyApplication {
    private MyBean myBean;

    public MyApplication(MyBean myBean) {
        this.myBean = myBean;
    }

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

Ma solution a été de déplacer la définition du bean dans un autre fichier de classe.

@Configuration
public CustomConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
3
Renato Back

j'ai rencontré cette erreur d'une manière assez stupide

@Autowired
// private Bean bean;

public void myMethod() {
  return;
}

ce qui s’est passé, c’est que j’ai commenté une ligne pour une raison quelconque et que j’ai laissé l’annotation qui faisait penser au printemps que la méthode devait être câblée automatiquement.

2
masadwin

En général, le traitement des dépendances circulaires consiste à utiliser l'injection de setter.

J'ai essayé le code d'injection de setter que vous avez posté, et cela a fonctionné pour moi. J'imagine que la raison pour laquelle vous obtenez l'exception est que Bean1 et Bean2 sont dans le package com.myapp.beans et que l'analyse de composant n'est pas activée pour ce package.

Vous devez ajouter les éléments suivants à votre configuration de ressort:

<context:component-scan base-package="com.bullethq.accounts.web"/>

ou déplacez les haricots vers un paquet analysé automatiquement par Spring.

1
John Farrelly