The postProcessBeanFactory empty method provided by AbstractApplicationContext
The method postProcessBeanFactory does not have the same name as the method in the BeanFactoryPostProcessor interface, but its function is to provide subclasses to add some additional functions, such as adding the implementation of the BeanPostProcessor interface, or customizing some other functions. You can get BeanFactory, and you can customize some functions of it.
Here is how the subclasses provided by Spring GenericWebApplicationContext
are implemented:
@Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { if (this.servletContext != null) { beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); } WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext); }
Here he registers a ServletContextAwreProcessor
to beanFactory
, which ServletContexAwareProcessor
is a BeanPostProcessor
subclass of an interface.
The highlight is BeanFactoryPostProcessor
AbstractApplicationContext#refresh
The method in the next analysis invokeBeanFactoryPostProcessors
, this method is used to register and execute BeanFactoryPostProcessor
.
Go directly to the source code:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 执行所有的BeanFactoryPostProcessor PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) // aop的处理 if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
The point is here:
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
The collection obtained first BeanFactoryPostProcessor
, all obtained here are added by the user when customizing BeanFactory
, add
enter this method:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. // Processed Beans Set<String> processedBeans = new HashSet<>(); // Advanced external BFPP Process and judge whether the current Factory is a BeanDefinitionRegistry if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // Save BFPP Bean List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // Save BDRPP Bean List <BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); / / Start processing external incoming BFPP for (BeanFactoryPostProcessor postProcessor :beanFactoryPostProcessors) { // Process BDRPP first if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // Directly call the interface method of BDRPP, and the following postProcessBeanFactory method will uniformly process registryProcessor.postProcessBeanDefinitionRegistry(registry ); // Add to the collection of BFPP registryProcessors.add(registryProcessor); } else { // Add to the collection of BDRPP regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Determine the current beanName Yes, they all implement PriorityOrdered // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. // Save the current BDRPP List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. // Press Type get BeanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // Add to the currently registered In the BDRPP collection currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // Add to the processed beans collection processedBeans.add(ppName); } } / / Sort the current BDRPP sortPostProcessors(currentRegistryProcessors, beanFactory); // Add all the current BDRPP to the set of BDRPP defined at the front registryProcessors.addAll(currentRegistryProcessors); // Execute the postProcessBeanDefinitionRegistry method of the current BDRPP invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors , registry); // clear the current BDRPP currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. // sort // Get bdrpp again, because the above execution may also add new bdrpp in postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // Determine whether it has been processed, and Whether the Ordered interface is implemented if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { // Add to the current BDRPP collection currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class )); // add to the processed set processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); // add to the BDRPP set registryProcessors.addAll(currentRegistryProcessors); // Execute bdrpp's postProcessBeanDefinitionRegistry method invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // Clear the current bdrpp collection currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; // Loop to get BDRPP, then sort and perform operations until all BDRPP are executed while (reiterate) { reiterate = false; // Get BDRPP postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor .class, true, false); for (String ppName : postProcessorNames) { // If it has been processed , execute BDRPP and exit the loop, otherwise continue the loop if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } // 排序 sortPostProcessors(currentRegistryProcessors, beanFactory); // 加入到BDRPP集合中 registryProcessors.addAll(currentRegistryProcessors); // 执行bdrpp invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. // Execute the postProcessBeanFactory method in invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); // Execute the postProcessBeanFactory method in bfpp invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // If it is not bdrpp, then directly execute the postProcessBeanFactory of bfpp // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } / / Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Get BFPP's beanName collection String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true , false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. // Define a BFPP List that implements PriorityOrdered<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // Define a collection that implements the Ordered interface // List <String> orderedPostProcessorNames = new ArrayList<>(); List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); // define an unordered collection // List<String> nonOrderedPostProcessorNames = new ArrayList<>(); List<BeanFactoryPostProcessor > nonOrderedPostProcessors = new ArrayList<>(); for (String ppName : postProcessorNames) { // don't do processing if already processed if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { // orderedPostProcessorNames.add(ppName); orderedPostProcessors.add(beanFactory.getBean(ppName,BeanFactoryPostProcessor.class)); } else { // nonOrderedPostProcessorNames.add(ppName); nonOrderedPostProcessors.add(beanFactory.getBean(ppName,BeanFactoryPostProcessor.class)); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. // Sort // for (String postProcessorName : orderedPostProcessorNames) { sortPostProcessors(priorityOrderedPostProcessors, beanFactory); // First execute the bfpp of the PriorityOrdered interface invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. // Here, the BFPP obtained from the Ordered interface is converted into a collection, and then sorted , and then execute, which can be directly merged here, // put it in this orderedPostProcessors collection when the above is obtained // List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); // orderedPostProcessors.add( beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); // } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. // Process unordered // List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); // for (String postProcessorName : nonOrderedPostProcessorNames) { // nonOrderedPostProcessors.add (beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); // } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, eg replacing placeholders in values... // Clear the cached metadata, because the BFPP's Execution, the property value of the BeanDefinition may have changed, such as using the property value of the placeholder beanFactory.clearMetadataCache(); }
This method is probably very long, but in fact it does a few things:
BeanFactoryPostProcessor
Execute the implementation of the external incoming first- The implementation
BeanFactoryPostProcessor
of the sub-interface that is processed firstBeanDefinitionRegistryPostProcessor
- When processing
BeanDefinitionRegistryPostProcessor
the implementation, first processPriorityOrdered
the implementation that implements the interface - After processing
PriorityOrdered
the class that implements the interface, then processOrdered
the implementation that implements the interface - After the implementation class of the
Ordered
interface is processed, the unsorted ones are processed - Processed
BeanDefinitionRegistryPostProcessor
implementation after processedBeanFactoryPostProcessor
implementation - The processing order is also
PriorityOreded
,Ordered
, not sorted
The approximate logic here is this, it may not seem to understand very well, draw a flow chart:
Through the flow chart, it can be simplified as: first traverse and execute the external input BFPP
, then execute BDRPP
, and then execute the BFPP
three parts, and each part may be sorted, sorted according to PriorityOrdered
, Ordered
, noSort
and then executed.
Explained here BeanDefinitionRegistryPostProcessor
, this interface is BeanFactoryPostProcessor
that it contains a method called postProcessBeanDefinitionRegistry
. This method is very important. This method ConfigurationClassPostProcessor
is used to parse annotations in the implementation class, and this class is also SpringBoot
the key to automatic assembly.
ConfigurationClassPostProcessor
When was this class added to the Spring
container?
When we start the container, the scan Spring
will be performed BeanDefinition
, if we xml
enable annotation scanning in the configuration file:
<context:component-scan base-package="com.redwinter.test"/>
Then at this time, more than one will be automatically added BeanDefinition
to the Spring
container, beanName
for org.springframework.context.annotation.internalConfigurationAnnotationProcessor
, there are several others:
Previous articleSpring source code (4) How to implement custom tags in Spring configuration files? - Ling, Xi- Blog Garden talks about custom tags. When spring parses xml, it is divided into default namespace and custom namespace, and context is a custom namespace. The parser of this tag is ComponentScanBeanDefinitionParser, this class The parse method in is parsing logic processing:
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. // 配置扫描器 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // 扫描BeanDefinition,在指定的包下 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 注册组件 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
This method executes the process:
BeanDefinition registerComponents
registerComponents
The method is ConfigurationClassPostProcessor
the place to add, because there is too much code, only part of the code is posted here:
// ... omit part of the code Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); // Determine whether the register contains org.springframework.context.annotation.internalConfigurationAnnotationProcessor // If not, add a BeanDefinition of ConfigurationClassPostProcessor // For parsing annotations if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { // Create a BeanDefinition as ConfigurationClassPostProcessor RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); // Register a beanName as org. springframework.context.annotation.internalConfigurationAnnotationProcessor // BeanDefinition, class is ConfigurationClassPostProcessor beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Create a BeanDefinition of AutowiredAnnotationBeanPostProcessor // for autowiring if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(;AutowiredAnnotationBeanPostProcessor.) def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // ...omit some code
A name is registered as a constant in the source code beanName
. CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME
This constant is org.springframework.context.annotation.internalConfigurationAnnotationProcessor
, class
for ConfigurationClassPostProcessor