Spring 5 source code analysis - container refresh - prepareBeanFactory() method

Last article: Spring 5 source code analysis - register configuration class

Previously, the definition of configuration class has been registered in the container. Before comprehensive analysis and processing of configuration class, Spring needs to do some preprocessing, such as setting class loader, setting post processor ApplicationContextAwareProcessor, adding three objects of environment systemProperties systemEnvironment to the container, and setting Spring framework not to Operations such as interfaces that need to be injected automatically.

The source code is as follows:

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Set class loader
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// It is very important to add BeanPostProcessor to complete the injection of Bean's related XXXAware interface
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

		// The following lines of code can ignore the given auto assembly dependent interfaces (that is, the auto injection of setter methods corresponding to these interfaces will not be executed)
		// For detailed documents, please refer to the blog: https://www.jianshu.com/p/3c7e0608ff1f
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		//The following four lines of code are all subclasses of ApplicationContext, except beanfactory is the beanfactory added,
		// For example, annotation config application context. You need to get objects from beanFactory or annotationconfigpplicationcontext when performing automatic assembly
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		// Blog address: https://www.cnblogs.com/wade-luffy/p/6078446.html
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		// Add three objects of environment systemProperties systemEnvironment to the container
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

ApplicationContextAwareProcessor

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

It is easy to see that the postProcessBeforeInitialization method of ApplicationContextAwareProcessor is to set the corresponding Environment EmbeddedValueResolver ResourceLoader ApplicationEventPublisher MessageSource ApplicationContext object in the XXXAware interface class. You can read the relevant value pairs in your implementation class To intervene in the conduct of an operation or framework.

For example:

@Component
@Getter
@Setter
public class IgnoreUser implements EnvironmentAware, ApplicationContextAware {
	private Environment environment;
	private ApplicationContext applicationContext;

	@Autowired
	private IgnoreDept dept;

	private String name;

	private Integer age;


	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}

	public void show(){
		System.out.println(environment.getActiveProfiles());
		System.out.println(applicationContext.getBean(IgnoreDept.class));
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}

Three built-in beans (environment systemProperties systemEnvironment)

Since it is a built-in Bean, which exists in the Spring container, you can get the corresponding Bean by using automatic injection by type

For example, use EnvironmentAware to let the Spring framework call the setEnvironment() method of the implementation class through post-processing, but it can be written in a different way

public class IgnoreUser implements /*EnvironmentAware, */ApplicationContextAware {
	@Autowired
	private Environment environment;

Note out the implements EnvironmentAware interface, and use @ Autowired directly

Keywords: Programming Spring

Added by RobReid on Tue, 12 Nov 2019 16:03:04 +0200