spring Core Post Processor-Configuration Class Post Processor

This blog is limited in ability, although some of it is incomplete. I hope it will be helpful to you.
Let's look at the inheritance diagram of the processor first.

There are two important attributes in this tool class, org. spring framework. context. annotation. Configuration ClassUtils

	private static final String CONFIGURATION_CLASS_FULL = "full";

	private static final String CONFIGURATION_CLASS_LITE = "lite";

How to explain these two attributes?

Full full, we can understand it as a whole and spring's corresponding lite can also be understood as a part.

So what does our protagonist @Configuration annotation have to do with these two attributes? Why does adding and not adding to configuration classes work in spring environments?

Let's look at the code in the environment first.

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

//test

public class MainDemo {

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

	}

}

The code breakpoint we entered into this class goes into debugging

 

Normally, this code will only enter else if because of the rigor of spring design. This code will parse all BDS in the registration list and place the classes with the @Configuration annotation detected in another bd collection for the next parse. In detection, the class with this annotation will be set to an attribute, isFull (abbreviated), or Lite (intermittent) attribute, and we will run to the next breakpoint to parse.

Second parsing in this kind of source code

	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;
		}

This code can be understood as putting a class with @Configuration in a map, returning directly if it is empty, and entering the following code if it is not empty.

The following code is not posted, we will see the results directly later, breakpoint back to the test class. Let's see what coloured eggs are.

 

Yes, cglib agent. If it's not added, it's not. Look directly at the result.

Why, that's one of the great things about spring rigor (the principle of singularity). Let's look at the following code

Look at the initialization environment code

@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);
	}

}

With or without the annotation, the printed result is init-user. What if you change it?

@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 This result will be printed once. Adding static keyword will invalidate

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

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

	@Bean
	public User getUserBean(){
		return new User();
	}
}
//This result will be printed twice.

But one problem is that the two hashcode s printed are the same, and the same is a singleton object.

Because of the limited level, the real reason is unknown.

The two hashcode s may be the same because spring takes the first time from the cached singleton pool (default singleton, can also be understood as singleton pool) and then from the real singleton pool (bean lifecycle call). Chains are steps like this.

Ability problems can only be remedied later, but also hope to help you. spring source code is too ugly, because it has not been proved, the online interpretation is not sure whether it is right (online posts are messy, it is difficult to find the right one).

Tags: Spring Attribute

Posted on Fri, 06 Sep 2019 20:23:38 -0700 by MeanMrMustard