una saber referencia quito permitir iterativo hay eliminar donde detectar cómo como calculo java spring dependency-injection autowired circular-reference

java - saber - referencia circular c#



Ejemplo de referencia circular de primavera (4)

Algunas lecturas al respecto:

http://blog.jdevelop.eu/?p=382

Tales dependencias circulares no son frías y deben evitarse cuando sea posible

Tengo una referencia circular en uno de mis proyectos en el trabajo usando Spring, que no puedo arreglar, y falla con el siguiente error al inicio:

''org.springframework.security.authenticationManager'': Requested bean is currently in creation: Is there an unresolvable circular reference?

Intenté recrear el mismo problema en un nivel más pequeño en un proyecto de muestra (sin todos los detalles de mi proyecto de trabajo). Sin embargo, no he podido encontrar un escenario plausible en el que la primavera falle con un error. Esto es lo que tengo:

public class ClassA { @Autowired ClassB classB; } public class ClassB { @Autowired ClassC classC; } @Component public class ClassC { @Autowired ClassA classA; } @Configuration public class Config { @Bean public ClassA classA() { return new ClassA(); } @Bean public ClassB classB() { return new ClassB(); } }

Tengo un escenario similar en mi proyecto, que falla, y esperaba que la primavera se quejara también en mi proyecto de muestra. ¡Pero funciona bien! ¿Puede alguien darme un ejemplo sencillo de cómo romper el resorte con el error de referencia circular?

Edición: solucioné el problema utilizando javax.inject.Provider. La única otra diferencia en los 2 proyectos fue que las anotaciones utilizadas fueron javax.inject.Inject y javax.annotation.ManagedBean en lugar de @Autowired y @Component.



Este es un hilo viejo, así que supongo que casi te olvidaste del problema, pero quiero hacerte saber sobre el misterio. Encontré el mismo problema, y ​​el mío no desapareció mágicamente, así que tuve que resolver el problema. Resolveré tus preguntas paso a paso.

1. ¿Por qué no se pudo reproducir la excepción de referencia circular?

Porque la primavera se encarga de ello. Crea frijoles y los inyecta según sea necesario .

2. Entonces, ¿por qué su proyecto produce la excepción?

  • Como dijo @sperumal, Spring puede producir una excepción circular si usa una inyección de constructor
  • De acuerdo con el registro, usas Spring Security en tu proyecto.
  • En la configuración de seguridad de Spring, ellos usan inyección de constructor
  • Sus beans que inyectan el authenticationManager tenían la referencia circular

3. Entonces, ¿por qué la excepción se ha ido místicamente?

La excepción puede o no ocurrir, depende del orden de creación de los beans. Supongo que *context.xml varios archivos *context.xml o algo así, y los cargas con la configuración algo como abajo en web.xml

<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:*-context.xml</param-value> </context-param>

Los archivos xml serán cargados por la clase XmlWebApplicationContext y el orden de carga de los archivos no está garantizado. Simplemente carga archivos desde el sistema de archivos. El problema está aquí. No hay problema si la clase carga primero el archivo de contexto de la aplicación, porque sus beans ya están creados cuando se usan para la inyección de construcción de Spring Security. Pero, si primero carga el archivo de contexto de Spring Security, ocurre un problema de referencia circular, porque Spring intenta usar sus beans en la inyección del constructor antes de que se hayan creado.

4. ¿Cómo resolver el problema?

Forzar el orden de carga de los archivos xml. En mi caso, cargué el archivo xml de contexto de seguridad al final del archivo de contexto de la aplicación usando <import resource=""> . El orden de carga se puede cambiar dependiendo de los entornos, incluso con el mismo código, por lo que recomiendo establecer el orden para eliminar posibles problemas.


Podría usar @Lazy para indicar que el frijol está creado perezosamente, rompiendo el ciclo impaciente de autowiring.

La idea es que algún bean en el ciclo podría ser instanciado como un proxy, y en el momento en que realmente se necesita se inicializará. Esto significa que todos los beans están inicializados excepto el que es un proxy. Su uso por primera vez activará la configuración y, como los otros beans ya están configurados, no será un problema.

De un número en Spring-Jira:

@Lazy anotación que se puede utilizar junto con @Configuration para indicar que todos los beans dentro de esa clase de configuración deben inicializarse perezosamente. Por supuesto, @Lazy también se puede utilizar junto con los métodos individuales de @Bean para indicar una inicialización perezosa de forma individual. https://jira.springsource.org/browse/SJC-263

Lo que significa que anotar tu bean como @Lazy sería suficiente. O si prefiere, simplemente anote la clase de configuración como @Lazy siguiente manera:

@Configuration @Lazy public class Config { @Bean public ClassA classA() { return new ClassA(); } @Bean public ClassB classB() { return new ClassB(); } }

Si implementas una interfaz de tus beans, esto funcionará bastante bien.