¿Cómo lo resuelve la primavera? El frijol A depende del frijol b, y el frijol b del frijol a.Dependencia circular en la primavera
Respuesta
Como han dicho las otras respuestas, Spring solo se encarga de ello, creando los granos e inyectándolos según sea necesario.
Una de las consecuencias es que la configuración de inyección/propiedad de frijol puede ocurrir en un orden diferente al que parecen implicar los archivos de su cableado XML. Por lo tanto, debe tener cuidado de que sus instaladores de propiedades no realicen la inicialización que depende de otros instaladores que ya hayan sido llamados. La forma de lidiar con esto es declarar que los beans implementan la interfaz InitializingBean
. Esto requiere que implemente el método afterPropertiesSet()
, y aquí es donde realiza la inicialización crítica. (También incluyo código para verificar que las propiedades importantes se hayan establecido realmente).
Simplemente lo hace. Crea instancias a
y b
, e inyecta cada una en la otra (usando sus métodos setter).
¿Cuál es el problema?
¿Funcionará con la inyección de constructor. – javaguy
@javaguy: No, no lo hará. – skaffman
@skaffman única forma con después de las propiedadesConfigurar el uso del método adecuado? – gstackoverflow
El Spring reference manual explica cómo se resuelven las dependencias circulares. Primero se crean instancias de los beans, luego se inyectan entre sí.
Considere esta clase:
package mypackage;
public class A {
public A() {
System.out.println("Creating instance of A");
}
private B b;
public void setB(B b) {
System.out.println("Setting property b of A instance");
this.b = b;
}
}
Y una clase similar B
:
package mypackage;
public class B {
public B() {
System.out.println("Creating instance of B");
}
private A a;
public void setA(A a) {
System.out.println("Setting property a of B instance");
this.a = a;
}
}
Si a continuación ha tenido este fichero de configuración:
<bean id="a" class="mypackage.A">
<property name="b" ref="b" />
</bean>
<bean id="b" class="mypackage.B">
<property name="a" ref="a" />
</bean>
se podría ver la siguiente salida cuando creando un contexto usando esta configuración:
Creating instance of A
Creating instance of B
Setting property a of B instance
Setting property b of A instance
Tenga en cuenta que no cuando se inyecta en a
b
, a
es inicializado todavía completamente.
Es por eso que Spring requiere un constructor sin argumentos ;-) –
¡No si usa argumentos de constructor en sus definiciones de bean! (Pero en ese caso no puede tener una dependencia circular.) –
@Richard Fearn ¿Su publicación trata sobre la explicación del problema en lugar de proporcionar la solución? – gstackoverflow
Desde el Spring Reference:
por lo general puede confiar en primavera para hacer lo correcto. Detecta problemas de configuración, como referencias a beans no existentes y dependencias circulares, en el contenedor load-time. Primavera establece las propiedades y resuelva las dependencias tan tarde como sea posible , cuando el grano es en realidad creado.
El contenedor Spring puede resolver dependencias circulares basadas en Setter pero ofrece una excepción de tiempo de ejecución BeanCurrentlyInCreationException en el caso de dependencias circulares basadas en Constructor. En caso de dependencia circular basada en Setter, el contenedor IOC lo maneja de forma diferente a un escenario típico en el que configuraría completamente el bean colaborador antes de inyectarlo. Para por ejemplo., Si Bean A tiene una dependencia sobre el Bean B y Bean B sobre el Bean C, el contenedor inicializa totalmente C antes de inyectarlo a B y una vez B está totalmente inicializado Se inyecta a A. Sin embargo, en caso de dependencia circular, uno de los granos se inyecta a la otra antes de que esté completamente inicializado.
En la base de código con la que estoy trabajando (1 millón de líneas de código) tuvimos un problema con los tiempos de inicio largos, de alrededor de 60 segundos. Estábamos recibiendo 12000+ FactoryBeanNotInitializedException.
lo que hice fue poner un breakpoint condicional en AbstractBeanFactory#doGetBean
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
donde hace destroySingleton(beanName)
Imprimí la excepción con condicional código de punto de ruptura:
System.out.println(ex);
return false;
Al parecer esto sucede cuando FactoryBean s participan en un gráfico de dependencia cíclica. Lo solucionamos implementando ApplicationContextAware y InitializingBean e inyectando manualmente los granos.
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class A implements ApplicationContextAware, InitializingBean{
private B cyclicDepenency;
private ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
ctx = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
cyclicDepenency = ctx.getBean(B.class);
}
public void useCyclicDependency()
{
cyclicDepenency.doSomething();
}
}
Esto reduce el tiempo de arranque a alrededor de 15 segundos.
Así que no siempre suponga que la primavera puede ser buena para resolver estas referencias por usted.
Por esta razón, recomendaría deshabilitar la resolución de dependencia cíclica con AbstractRefreshableApplicationContext#setAllowCircularReferences(false) para evitar muchos problemas futuros.
Interesante recomendación. Mi recomendación contraria sería solo hacer eso si * sospechas * que las referencias circulares están causando un problema de rendimiento. (Sería una pena romper algo que no necesita ser roto tratando de solucionar un problema que no necesita ser reparado). –
Es una pendiente resbaladiza hasta el infierno de mantenimiento para permitir dependencias circulares, rediseñando su arquitectura de circular las dependencias pueden ser realmente engañosas, como en nuestro caso. Lo que más o menos significaba para nosotros era que obtuvimos el doble de conexiones a la base de datos durante el inicio, ya que sessionfactory estaba involucrado en la dependencia circular. En otros escenarios, cosas mucho más desastrosas podrían haber ocurrido debido a que el bean fue instanciado más de 12000 veces. Claro que deberías escribir tus granos para que apoyen la destrucción de ellos, pero ¿por qué permitir este comportamiento en primer lugar? – jontejj
@jontejj, usted merece una galleta – serprime
Si por lo general utiliza el constructor de la inyección y no quiere cambiar a la propiedad de la inyección y luego de búsqueda método: inyección de primavera deja un grano lookup perezosamente la otra y por lo tanto el principio Solución dependencia cíclica. Ver aquí: http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#d0e1161
Say A depende de B, entonces la primavera primera instancia será propiedades A, entonces B, entonces B establecidos para, a continuación, el conjunto B en A.
Pero lo que si B también depende de A?
Según tengo entendido: Spring acaba de encontrar que A ha sido construido (constructor ejecutado), pero no completamente inicializado (no todas las inyecciones hechas), bueno, pensó, está bien, es tolerable que A no esté completamente inicializado, solo Por ahora, configure las instancias A no iniciadas por completo en B. Después de que B se inicializó por completo, se estableció en A, y finalmente, A se inició completamente ahora.
En otras palabras, solo expone A a B por adelantado.
Para las dependencias a través del constructor, Sprint acaba de lanzar BeanCurrentlyInCreationException, para resolver esta excepción, establezca lazy-init en true para el bean que depende de otras a través del modo constructor-arg.
Se explica claramente here. Gracias a Eugen Paraschiv.
La dependencia circular es un olor de diseño, ya sea solucionarlo o utilizar @Lazy para la dependencia que causa problemas para solucionarlo.
Al usar Setter Injection o Field Injection o al usar @Lazy para la dependencia.
Si dos beans dependen el uno del otro, no deberíamos usar la inyección de Constructor en ambas definiciones de bean. En cambio, tenemos que usar la inyección setter en cualquiera de los beans.(Por supuesto, podemos usar la inyección de setter n tanto las definiciones de frijol, pero las inyecciones constructor tanto en tiro 'BeanCurrentlyInCreationException'
Consulte doc primavera en "https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources-resource"
Problema ->
Class A {
private final B b; // must initialize in ctor/instance block
public A(B b) { this.b = b };
}
Class B {
private final A a; // must initialize in ctor/instance block
public B(A a) { this.a = a };
}
// Causado por: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error al crear bean con el nombre 'A': Bean solicitado se encuentra actualmente en la creación: ¿Hay una referencia circular no resuelta?
Solu ción 1 ->
Class A {
private B b;
public A() { };
//getter-setter for B b
}
Class B {
private A a;
public B() { };
//getter-setter for A a
}
Solución 2 ->
Class A {
private final B b; // must initialize in ctor/instance block
public A(@Lazy B b) { this.b = b };
}
Class B {
private final A a; // must initialize in ctor/instance block
public B(A a) { this.a = a };
}
- 1. dependencia circular en C++
- 2. Dependencia circular en Python
- 3. MVC - dependencia circular
- 4. Solución de Dependencia Circular
- 5. Dependencia circular en clases Java
- 6. primavera ejemplo de referencia circular
- 7. ¿Resuelve la dependencia de typedef circular?
- 8. MVP con CDI; evitando la dependencia circular
- 9. ¿Cómo resuelvo esta dependencia circular?
- 10. SQLAlchemy dependencia circular - cómo resolverlo?
- 11. Mejor práctica de dependencia circular
- 12. Tratando con una dependencia circular
- 13. circular dependencia de las importaciones en Python
- 14. dependencia circular en el marco de entidad
- 15. ¿Cómo deshacerse de esta dependencia circular?
- 16. joyero añade dependencia circular a mi joya
- 17. Guice proxy para apoyar dependencia circular
- 18. Posible problema de dependencia circular con la aplicación PHP
- 19. La dependencia de las anotaciones de la primavera
- 20. Dependencia circular en el patrón del mediador usando C#
- 21. Inyectar dependencia de primavera en super clase abstracta
- 22. Resolviendo una dependencia circular entre clases de plantilla
- 23. C++ - dependencia circular (utilizando el tipo interno de la subclase en la clase base con plantilla)
- 24. Cualquier herramienta para verificar la dependencia circular en un proyecto Delphi
- 25. Inyección de dependencia de primavera @Autocableado sin setter
- 26. Dependencia de primavera Inyección de un aspecto anotado
- 27. No se puede agregar la referencia al proyecto debido a un error de dependencia circular
- 28. Resolving circular depenency
- 29. Inyectando el Inyector de Dependencia usando la Inyección de Dependencia
- 30. ¿Cómo se excluye la dependencia de registro común de primavera con hiedra?
buen artículo http://www.baeldung.com/circular-dependencies-in-spring – gstackoverflow