Introducción: Una dependencia circular es una referencia anidada de bucle en las clases N. Si esta dependencia circular ocurre en el desarrollo diario utilizando el método de Nuevo Objeto, el programa continuará llamando a la bucle en tiempo de ejecución hasta que la memoria se desborda e informa un error. Hablemos de la primavera si resuelve dependencias circulares.
El primer tipo: dependencia cíclica del parámetro del constructor
El contenedor de primavera colocará cada identificador de frijoles que se crea en un "grupo de frijoles actual" y el identificador de frijoles permanecerá en este grupo durante el proceso de creación. Por lo tanto, si encuentra que ya está en la "piscina de frijoles actual" durante el proceso de creación, se lanzará.
La excepción de BeanCurrentlyIncreationException indica una dependencia circular; El frijol creado se eliminará de la "piscina de frijoles creada actualmente".
Primero inicializamos tres frijoles.
Public Class StudentA {StudentB StudentB privado; public void setstudentb (Studentb StudentB) {this.studentb = studentb; } public stentudentA () {} public StudentA (Studentb StudentB) {this.studentb = studentb; }} Public Class StudentB {StudentC StudentC privado; public void setstudentc (StudentC StudentC) {this.studentc = studentc; } public studentb () {} public StudentB (StudentC StudentC) {this.studentc = studentc; }} Estudiante de clase pública {estudiante privado estudiantil; public void setStudenta (StudentA StudentA) {this.studenta = sententer; } public studentc () {} public StudentC (Student StudentA) {this.studenta = sententra; }}Ok, lo anterior son tres clases muy básicas. Estructura de parámetros StudentA es StudentB. La estructura de parámetros de Studentb es StudentC, y la estructura de parámetros de StudentC es StudentA, que crea una situación de dependencia circular.
Todos entregamos estos tres frijoles a la gestión de la primavera y los instanciaron con construcciones de parámetros
<bean id = "a"> <constructor-arg index = "0" ref = "b"> </ constructor-arg> </ bean> <bean id = "b"> <constructor-arg index = "0" ref = "c"> </ constructor-arg> </bean> <bean id = "c"> <constructor-arg index = "0" ref = "a" <a "<a" <a "<a" <a "<A" </"</argor-arg>
Aquí está la clase de prueba:
Prueba de clase pública {public static void main (string [] args) {applicationContext context = new ClassPathXMLApPlicationContext ("com/zfx/student/applicationContext.xml"); //System.out.println(context.getBean("a ", sterals.class)); }}El mensaje de error del resultado de la ejecución es:
Causado por: org.springframework.beans.factory.BeherCurrentlyIncreationException:
Error a crear frijoles con el nombre 'A': Bean solicitado está actualmente en la creación: ¿Existe una referencia circular no resolidable?
Si comprende la oración al principio, no debe sorprenderse al informar este error. El contenedor de primavera primero crea una estudiante singleton. StudentA depende de StudentB, y luego pone una "piscina actual de frijoles". En este momento, StudentB se crea, StudentB depende de StudentC, y luego B se coloca en la "piscina de frijoles actual". En este momento, StudentC se crea, StudentC depende de StudentA. Sin embargo, en este momento, el estudiante ya está en la piscina, por lo que se informará un error. Debido a que todos los frijoles en la piscina no se han inicializado, dependerán de los errores. (El frijol inicializado se eliminará de la piscina)
El segundo tipo: método setter singleton, método predeterminado
Si desea hablar sobre la inyección de setter, es mejor que miremos una imagen de los frijoles instanciantes en primavera
Como se muestra en los dos primeros pasos de la figura, Spring instancia el objeto Bean y luego establece las propiedades del objeto.
Modifique el archivo de configuración para inyectarlo en modo establecer:
< name = "Studenta" ref = "A"> </property> </ Bean>
Aquí está la clase de prueba:
Prueba de clase pública {public static void main (string [] args) {applicationContext context = new ClassPathXMLApPlicationContext ("com/zfx/student/applicationContext.xml"); System.out.println (context.getBean ("a", sterals.class)); }}El resultado de la impresión es:
com.zfx.student.studenta@1fbfd6
¿Por qué no informa un error utilizando el método establecido?
Veamos la imagen de arriba. Spring primero instancia el objeto Bean usando construcciones. En este momento, Spring colocará el objeto instanciado en un mapa, y Spring proporciona un método para obtener la referencia de objeto instanciado con el atributo Unset. Basado en nuestro ejemplo, cuando Spring instancia StudentA, StudentB y StudentC, establecerá las propiedades del objeto. En este momento, StudentA confiará en StudentB y eliminará el objeto Singleton StudentB en el mapa, y así sucesivamente, no habrá problema de bucle.
El siguiente es el método de implementación en el código fuente de Spring. El siguiente código fuente se encuentra en la clase de JaVa en el paquete de Bean
/ ** Caché de objetos Singleton: Nombre de frijoles -> Instance de frijoles (colección de mapas que almacena objetos instanciados singleton)*/ mapa final privado <string, object> singletOnObjects = new concurrenthashmap <string, object> (64); / ** Caché de fábricas de singleton: nombre de frijol -> ObjectFactory (colección de caché de frijoles de fábrica de Singleton)*/ Maps private final <String, ObjectFactory> SingletOnFactory = new HashMap <String, ObjectFactory> (16); / ** Caché de los primeros objetos singleton: nombre de frijoles -> instancia de frijol*/ mapa final privado <string, object> EarlySingLetOnObjects = new HashMap <String, Object> (16); / ** Conjunto de singletons registrados, que contienen los nombres de frijoles en la orden de registro*/ Set Final Private <String> registredSingletons = new LinkedHashset <String> (64); /*** Agregar una instancia de singleton* Resuelva el problema de las referencias circulares* Agregue la fábrica de singleton dada para construir el singleton especificado* si es necesario. * <P> Para ser llamado a un registro ansioso de singletons, por ejemplo, poder * resolver referencias circulares. * @param beanName El nombre del bean * @param singletonFactory La fábrica para el objeto singleton */ protegido void addSingletOnFactory (String BeanName, ObjectFactory SingletOnFactory) {Afirme.Notnull (SingletAnfactory, "Singleton Factory no debe ser null"); sincronizado (this.singletOnObjects) {if (! this.singletOnObjects.containskey (beanName)) {this.singletonfactories.put (beanName, singletAnfactory); this.arlysingletOnObjects.remove (BeanName); this.RegisteredSingletons.add (BeanName); }}El tercer tipo: prototipo de setter, prototipo
Modificar el archivo de configuración a:
<bean id = "a" <<span style = "color:#ff0000;"> scope = "prototype" </span >> <propiedad name = "studentb" ref = "b"> </propiety> </bean> <bean id = "b" <span style = "color:#ff0000;"> scope = "prototipo" </span >> <name de propiedad = "studentc" ref = "c" <c "<c" <c "<c" <c "/</</d. id = "c" <span style = "color:#ff0000;"> scope = "prototype" </span >> <propiedad name = "studentc" ref = "c"> </propial> </ bean> <bean id = "c" <span style = "color:#ff0000;"> Scope = "Prototype" </span> <name de la propiedad = "refer" ref = "a" <a "<a" <a "<A" <A "<A" <apropiado </propiedad.
Scope = "Prototype" significa que se crea un objeto de instancia cada vez que solicita. La diferencia entre los dos es: los frijoles con estado usan el alcance prototipo, mientras que el alcance sin atacante generalmente usa el alcance singleton singleton.
Casos de prueba:
Prueba de clase pública {public static void main (string [] args) {applicationContext context = new ClassPathXMLApPlicationContext ("com/zfx/student/applicationContext.xml"); <strong> // En este momento, debe obtener una instancia de Spring Managed, porque ahora Scope = "Prototype" solo instanciará el objeto al solicitar obtener </strong> system.out.println (context.getBean ("a", sententerA.class)); }} Resultado de impresión:
Causado por: org.springframework.beans.factory.BeherCurrentlyIncreationException: Error al crear frijoles con el nombre 'a': El bean solicitado está actualmente en la creación: ¿hay una referencia circular no resolutable?
¿Por qué el modelo prototipo está mal?
Para los frijoles de alcance "prototipo", el contenedor de resorte no puede completar la inyección de dependencia porque el contenedor de resorte no almacena en caché los frijoles en los frijoles con "prototipo", por lo que un frijol creado no puede expuestos de antemano.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.