NOTE

2. Call BeanFactoryPostProcessor's postProcess Method

1. Code to study 2. Process BeanDefinitionRegistryPostProcessors 3. Process BeanFactoryPostProcessors

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Code to Study

  • AbstractApplicationContext.invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // Pass in the current Bean factory and all Bean-factory PostProcessors.
    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)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

The key line is:

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

It passes the current Bean factory and all Bean-factory PostProcessors into PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors.

  • PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<String>();

    // The current Bean factory is a BeanDefinitionRegistry [yes].
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();

        // Iterate over the beanFactoryPostProcessors passed in.
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // If it is a BeanDefinitionRegistryPostProcessor:
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                // Call its postProcessBeanDefinitionRegistry method.
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // Add it to registryProcessors.
                registryProcessors.add(registryProcessor);
            }
            // Otherwise add it to regularPostProcessors.
            else {
                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!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // Obtain the names of all PostProcessors of type BeanDefinitionRegistryPostProcessor from the Bean factory.
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        // Iterate over these PostProcessors. If one is PriorityOrdered, obtain its instance
        // from the Bean factory and save it in currentRegistryProcessors.
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // Sort, call postProcessBeanDefinitionRegistry, then clear the collection.
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // Iterate over these PostProcessors. If one is Ordered, obtain its instance
        // from the Bean factory and save it in currentRegistryProcessors.
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // Sort, call postProcessBeanDefinitionRegistry, then clear the collection.
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        // Iterate over these PostProcessors. If one is an ordinary type, obtain its instance
        // from the Bean factory and save it in currentRegistryProcessors.
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            // Sort, call postProcessBeanDefinitionRegistry, then clear the collection.
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // The next two lines call postProcessBeanFactory on all processors
        // (PriorityOrdered, Ordered, and ordinary), rather than postProcessBeanDefinitionRegistry.
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }
    // The current Bean factory is not a BeanDefinitionRegistry.
    else {
        // Invoke factory processors registered with the context instance.
        // Only call postProcessBeanFactory.
        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!
    // Obtain the names of all PostProcessors of type BeanFactoryPostProcessor from the Bean factory.
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // Iterate over these PostProcessors and put PriorityOrdered, Ordered,
    // and ordinary processors into three collections.
    for (String ppName : postProcessorNames) {
        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);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    // Sort and call postProcessBeanFactory on PriorityOrdered BeanFactoryPostProcessors.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    // Sort and call postProcessBeanFactory on Ordered BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    // Sort and call postProcessBeanFactory on ordinary BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    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, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}

2. Process PostProcessors of Type BeanDefinitionRegistryPostProcessor

2.1. The Current Bean Factory Is a BeanDefinitionRegistry

// The current Bean factory is a BeanDefinitionRegistry [yes].
if (beanFactory instanceof BeanDefinitionRegistry) {
//...
}

2.1.1. Process the beanFactoryPostProcessors Passed In

// Iterate over the beanFactoryPostProcessors passed in.
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
   //...
}
2.1.1.1. If It Is a BeanDefinitionRegistryPostProcessor, Call postProcessBeanDefinitionRegistry
// If it is a BeanDefinitionRegistryPostProcessor:
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    BeanDefinitionRegistryPostProcessor registryProcessor =
            (BeanDefinitionRegistryPostProcessor) postProcessor;
    // Call its postProcessBeanDefinitionRegistry method.
    registryProcessor.postProcessBeanDefinitionRegistry(registry);
    // Add it to registryProcessors.
    registryProcessors.add(registryProcessor);
}
// Otherwise add it to regularPostProcessors.
else {
    regularPostProcessors.add(postProcessor);
}

2.1.2. Process Other BeanDefinitionRegistryPostProcessors in beanFactory

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// Obtain the names of all PostProcessors of type BeanDefinitionRegistryPostProcessor from the Bean factory.
String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
2.1.2.1. First Call postProcessBeanDefinitionRegistry on PriorityOrdered Types
// Iterate over these PostProcessors. If one is PriorityOrdered, obtain its instance
// from the Bean factory and save it in currentRegistryProcessors.
for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
// Sort, call postProcessBeanDefinitionRegistry, then clear the collection.
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
2.1.2.2. Then Call postProcessBeanDefinitionRegistry on Ordered Types
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// Iterate over these PostProcessors. If one is Ordered, obtain its instance
// from the Bean factory and save it in currentRegistryProcessors.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}

// Sort, call postProcessBeanDefinitionRegistry, then clear the collection.
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
2.1.2.3. Finally Call postProcessBeanDefinitionRegistry on Ordinary Types
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// Iterate over these PostProcessors. If one is an ordinary type, obtain its instance
// from the Bean factory and save it in currentRegistryProcessors.
boolean reiterate = true;
while (reiterate) {
    reiterate = false;
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
        if (!processedBeans.contains(ppName)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
            reiterate = true;
        }
    }
    // Sort, call postProcessBeanDefinitionRegistry, then clear the collection.
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
}
2.1.2.4. Finally, Likewise Classify and Call postProcessBeanFactory
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// The next two lines call postProcessBeanFactory on all processors
// (PriorityOrdered, Ordered, and ordinary), not postProcessBeanDefinitionRegistry.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

2.2. The Current Bean Factory Is Not a BeanDefinitionRegistry

// The current Bean factory is not a BeanDefinitionRegistry.
else {
    // Invoke factory processors registered with the context instance.
    // Only call postProcessBeanFactory.
    invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

2.2.1. Only Call postProcessBeanFactory

3. Process PostProcessors of Type BeanFactoryPostProcessor

// Obtain the names of all PostProcessors of type BeanFactoryPostProcessor from the Bean factory.
String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

3.1. Divide Them into PriorityOrdered, Ordered, and Ordinary Types

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
// Iterate over these PostProcessors and put PriorityOrdered, Ordered,
// and ordinary processors into three collections.
for (String ppName : postProcessorNames) {
    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);
    }
    else {
        nonOrderedPostProcessorNames.add(ppName);
    }
}

3.2. Call Their postProcessBeanFactory Methods

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// Sort and call postProcessBeanFactory on PriorityOrdered BeanFactoryPostProcessors.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// Sort and call postProcessBeanFactory on Ordered BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
    orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
// Sort and call postProcessBeanFactory on ordinary BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub