Spring core post procesador-ConfigurationClassPostProcessor

Debido a la capacidad limitada de este blog, aunque algunos están incompletos, espero que les sea de utilidad.
Echemos un vistazo al diagrama de herencia del procesador.

Hay dos propiedades muy importantes en esta clase de herramienta org.springframework.context.annotation.ConfigurationClassUtils

	private static final String CONFIGURATION_CLASS_FULL = "full";

	private static final String CONFIGURATION_CLASS_LITE = "lite";

Cómo explicar estos dos atributos

completo, podemos entenderlo como todo y la lite correspondiente en primavera también se puede entender como una parte

Entonces, ¿cuál es la relación entre nuestra anotación @Configuration protagonista y estos dos atributos? ¿Por qué el entorno de primavera tiene efecto al agregar o no agregar en la clase de configuración?

Veamos primero el código en el entorno.

@Configuration
//@Import(TestImportSelector.class)
//@TestImportSelectorAnno
//@TestBeanFactoryPostProcessorAnno
@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {
}

//测试

public class MainDemo {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac =
				new AnnotationConfigApplicationContext(ScanConfig.class);
		ScanConfig scanConfig = (ScanConfig) ac.getBean("scanConfig");

	}

}

Ingresemos el punto de interrupción de este código de esta clase para depurar

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
            //断点调式
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}
		//给配置类产生cglib代理。加了@Configuration注解的
		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

 

En circunstancias normales, este código solo ingresará else si debido al rigor del diseño del resorte, este código analizará todos los bd en la lista de registro (BeanDefinition) y colocará la clase detectada con anotaciones @Configuration en otra colección de bd. análisis. En la detección se configurará un atributo de la clase con la anotación, que es isFull (abreviatura), y el que no lo es es el atributo lite (también intermitente). Pasamos al siguiente análisis de breakpoint

El segundo análisis en este tipo de código fuente

	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
				if (!(beanDef instanceof AbstractBeanDefinition)) {
					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
				}
				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
							"' since its singleton instance has been created too early. The typical cause " +
							"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
							"return type: Consider declaring such methods as 'static'.");
				}
				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
			}
		}
		if (configBeanDefs.isEmpty()) {
			// nothing to enhance -> return immediately
			return;
		}

Este fragmento de código se puede entender de esta manera. Ponga la clase con @Configuration en un mapa, si está vacío, regresará directamente, si no está vacío, ingrese el siguiente código,

El siguiente código no se publicará, sabremos el resultado más tarde y el punto de interrupción volverá a la clase de prueba. Veamos qué huevos de pascua

 

Sí, proxy cglib. Si no lo agrega, no es el caso, solo mire el resultado

Este es uno de los puntos fuertes del rigor del resorte (principio singleton). Primero veamos el siguiente fragmento de código

Mira el código de entorno inicializado

@Configuration
@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {

	@Bean
	public Test getTestBean(){
		return new Test();
	}

	@Bean
	public User getUserBean(){
		return new User();
	}
}

public class Test {

	public Test(){}
}

public class User {

	public User(){
		System.out.println("init-user");
	};
}

public class MainDemo {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac =
				new AnnotationConfigApplicationContext(ScanConfig.class);
	}

}

Si este comentario se agrega o no, el resultado impreso es todo init-user, si lo cambia

@Configuration
@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {

	@Bean
	public Test getTestBean(){
		getUserBean();
		return new Test();
	}

	@Bean
	public User getUserBean(){
		return new User();
	}
}
//cglib此结果会打印一次.加入static关键字会失效

@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {

	@Bean
	public Test getTestBean(){
		getUserBean();
		return new Test();
	}

	@Bean
	public User getUserBean(){
		return new User();
	}
}
//此结果会打印两次

Pero hay un problema: los dos códigos hash impresos son iguales, y el mismo es el objeto de un singleton.

Debido al nivel limitado, se desconoce la verdadera razón.

Los dos códigos hash pueden ser iguales porque Spring lo tomará primero del grupo de singleton en caché (el valor predeterminado es un singleton, o puede entenderse como un grupo de singleton) al crear un objeto (desde el grupo de singleton en caché, yo no saber si es una solución. Problema de dependencia circular) Por primera vez, tómelo del grupo de singleton real (la cadena de llamada del ciclo de vida del bean es un paso así)

El problema de la capacidad solo se puede solucionar más tarde y espero que te ayude. El código fuente de Spring es demasiado feo. Como no hay pruebas, no sé si la explicación en línea es correcta (las publicaciones en línea son desordenadas, quiere encontrar uno correcto. Difícil de encontrar).

Supongo que te gusta

Origin blog.csdn.net/qq_38108719/article/details/100592018
Recomendado
Clasificación