The Spring container initializes the refresh() method _02

Your praise is my biggest motivation. Look forward to working with you and making progress together.

Before the article arrived, AbstractApplicationContext. Refresh () method, ten several process in the method, in the previous article introduces the refresh () in the first four processes. This article focuses on invokeBeanFactoryPostProcessors (the beanFactory). This code is the focus of the process, which is analyzed in detail in this article.

5.invokeBeanFactoryPostProcessors()

5.1 The method calls the flow procedure

Step 1: AbstractApplicationContext# invokeBeanFactoryPostProcessors (ConfigurableListableBeanFactory the beanFactory)

Step 2: PostProcessorRegistrationDelegate. InvokeBeanFactoryPostProcessors (the beanFactory, getBeanFactoryPostProcessors ());

2.1 registryProcessor. PostProcessBeanDefinitionRegistry (registry) processing custom BeanDefinitionRegistryPostProcessor subclasses of 2.2 DefaultListableBeanFactory.getBeanNamesForType(java.lang.Class<? >, Boolean, Boolean) get a name of Ben by typeCopy the code

Step 3: PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors() Within a spring BeanDefinitionRegistryPostProcessor interface is realized

The first step (4) : PostProcessor. PostProcessBeanDefinitionRegistry (registry) different subclasses to deal with your own implementation class, here, the inside of the spring so far there is only one, That is ConfigurationClassPostProcessor class, the class is spring built-in.

Step 5: ConfigurationClassPostProcessor# processConfigBeanDefinitions (), processing ConfigurationClassPostProcessor

Step 6: ConfigurationClassUtils. CheckConfigurationClassCandidate ()

Step 7: ConfigurationClassParser

ConfigurationClassParser#parse(Set)

Note: The parse() method here is very important and will be covered in detail in the next article, but let’s take a look at the code logic involved in the previous steps!!

5.2 invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    / * ** getBeanFactoryPostProcessors () to obtain a custom (our own implementation, and not to the spring management)* /
    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())); } Copy the code

The BeanFactoryPostProcessor implementation is a subclass of this class that spring does not manage, as shown in the following example:

public class TestFactoryPostProcessor implements BeanFactoryPostProcessor {


 @Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
 int count = beanFactory.getBeanDefinitionCount();  String[] names = beanFactory.getBeanDefinitionNames();  System.out.println("Currently in the BeanFactory"+count+"Beans");  System.out.println(Arrays.asList(names));  } } Copy the code

This way, through getBeanFactoryPostProcessors get ().

5.2.0 sequence diagram
InvokeBeanFactoryPostProcessors sequence diagram
5.2.1 invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();
  /** Handling of BeanDefinitionRegistry types */  if (beanFactory instanceof BeanDefinitionRegistry) {  BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;  List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();  / * * * BeanDefinitionRegistryPostProcessor * /  List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();  /** Custom BeanFactoryPostProcessor*/  for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {  if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {  BeanDefinitionRegistryPostProcessor registryProcessor =  (BeanDefinitionRegistryPostProcessor) postProcessor;  / * ** for BeanDefinitionRegistryPostProcessor types,* There are its own methods based on BeanFactoryPostProcessor* Needs to be called first* /  registryProcessor.postProcessBeanDefinitionRegistry(registry);  registryProcessors.add(registryProcessor);  }  else {  / * ** Document the regular BeanFactoryPostProcessor* /  regularPostProcessors.add(postProcessor);  }  }   / * ** currentRegistryProcessors is put inside the spring BeanDefinitionRegistryPostProcessor interface is realized* /  List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();   // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.  / * ** getBeanNamesForType() gets the name of Ben from type, which refers to the class type of the Spring bean description file* /  String[] postProcessorNames =  beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);  / * ** This BeanFactory is originally registered by spring by default* /  for (String ppName : postProcessorNames) {  if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {  currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));  processedBeans.add(ppName);  }  }  / * ** ordering* /  sortPostProcessors(currentRegistryProcessors, beanFactory);  / * ** merge list* /  registryProcessors.addAll(currentRegistryProcessors);  / * ** in the spring Whether their definition or built-in BeanDefinitionRegistryPostProcessor* is handled here, for example {@linkThe processing of ConfigurationClassPostProcessor}* Here is the important code...* /  invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  /** clear list */  currentRegistryProcessors.clear();   // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.  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);  }  }  sortPostProcessors(currentRegistryProcessors, beanFactory);  registryProcessors.addAll(currentRegistryProcessors);  invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  currentRegistryProcessors.clear();   // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.  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;  }  }  sortPostProcessors(currentRegistryProcessors, beanFactory);  registryProcessors.addAll(currentRegistryProcessors);  invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  currentRegistryProcessors.clear();  }   / * ** Execute the callback to BeanFactoryPostProcessor* perform here is a subclass of spring BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor callback methods * * /  invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);  / * ** This is the postProcessBeanFactory() method of BeanFactoryPostProcessor* /  invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);  }   else {  // 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!  String[] postProcessorNames =  beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);   // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,  // Ordered, and the rest.  List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();  List<String> orderedPostProcessorNames = new ArrayList<>();  List<String> nonOrderedPostProcessorNames = new ArrayList<>();  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.  sortPostProcessors(priorityOrderedPostProcessors, beanFactory);  invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);   // Next, invoke the BeanFactoryPostProcessors that implement Ordered.  List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();  for (String postProcessorName : orderedPostProcessorNames) {  orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));  }  sortPostProcessors(orderedPostProcessors, beanFactory);  invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);   // Finally, invoke all other BeanFactoryPostProcessors.  List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();  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(); } Copy the code
5.2.2 invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    / * ** all BeanDefinitionRegistryPostProcessor cycles* /  for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {  / * ** according to the different BeanDefinitionRegistryPostProcessors implementation* to call different postProcessBeanDefinitionRegistry method* /  postProcessor.postProcessBeanDefinitionRegistry(registry);  } } Copy the code

By the above method, can only in Spring processing programmers define their own Spring BeanFactoryPostProcessor first, and then in the treatment of the built-in in the Spring, the latter said to its management BeanDefinitionRegistryPostProcessor, One is spring BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor subclasses. So far the only one in the Spring of the built-in BeanDefinitionRegistryPostProcessor implementation class is ConfigurationClassPostProcessor is the next ConfigurationClassPostProcessor processing.

5.3 ConfigurationClassPostProcessor processing

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
 }  if (this.factoriesPostProcessed.contains(registryId)) {  throw new IllegalStateException(  "postProcessBeanFactory already called on this post-processor against " + registry);  }  this.registriesPostProcessed.add(registryId);  / * ** handle ConfigurationClassPostProcessor* /  processConfigBeanDefinitions(registry); } Copy the code

The real processing is done through processConfigBeanDefinitions ConfigurationClassPostProcessor

5.3.1 processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    /** Store the spring bean description file */
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    /** Get the names of all registered beans in the container */
    String[] candidateNames = registry.getBeanDefinitionNames();
  for (String beanName : candidateNames) {  /** Get the bean description file */ according to beanName  BeanDefinition beanDef = registry.getBeanDefinition(beanName);  if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||  ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {  if (logger.isDebugEnabled()) {  logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);  }  }  / * ** Check whether the Configuration class is included@Configurationannotations* checkConfigurationClassCandidate () pay attention to this method* /  else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {  /** if (**)@Configuration Encapsulate this class as BeanDefinitionHolder and put it in the configScript* This will be used later in the analysis* /  configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));  }  }   // Return immediately if no @Configuration classes were found  if (configCandidates.isEmpty()) {  return;  }   // Sort by previously determined @Order value, if applicable  configCandidates.sort((bd1, bd2) -> {  int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());  int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());  return Integer.compare(i1, i2);  });   // Detect any custom bean name generation strategy supplied through the enclosing application context  SingletonBeanRegistry sbr = null;  if (registry instanceof SingletonBeanRegistry) {  sbr = (SingletonBeanRegistry) registry;  if (!this.localBeanNameGeneratorSet) {  BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);  if(generator ! =null) {  this.componentScanBeanNameGenerator = generator;  this.importBeanNameGenerator = generator;  }  }  }   if (this.environment == null) {  this.environment = new StandardEnvironment();  }   // Parse each @Configuration class  /** Instantiate ConfigurationClassParser to resolve each configuration */  ConfigurationClassParser parser = new ConfigurationClassParser(  this.metadataReaderFactory, this.problemReporter, this.environment,  this.resourceLoader, this.componentScanBeanNameGenerator, registry);  / * ** Instantiate two Set candidates to undo the configCandidates previously added* Because there may be multiple configuration classes that duplicate* alreadyParsed is used to determine whether it has been processed* /  Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);   Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());  do {  / * *Parsing annotation classes,* Here is the key code* /  parser.parse(candidates);   parser.validate();   Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());  configClasses.removeAll(alreadyParsed);   // Read the model and create bean definitions based on its content  if (this.reader == null) {  this.reader = new ConfigurationClassBeanDefinitionReader(  registry, this.sourceExtractor, this.resourceLoader, this.environment,  this.importBeanNameGenerator, parser.getImportRegistry());  }  / * ** loadBeanDefinitions()@ImportThe class of* /  this.reader.loadBeanDefinitions(configClasses);  alreadyParsed.addAll(configClasses);   candidates.clear();  if (registry.getBeanDefinitionCount() > candidateNames.length) {  String[] newCandidateNames = registry.getBeanDefinitionNames();  Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));  Set<String> alreadyParsedClasses = new HashSet<>();  for (ConfigurationClass configurationClass : alreadyParsed) {  alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());  }  for (String candidateName : newCandidateNames) {  if(! oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName);  if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && ! alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName));  }  }  }  candidateNames = newCandidateNames;  }  }  while(! candidates.isEmpty());  // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes  if(sbr ! =null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {  sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());  }   if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {  // Clear cache in externally provided MetadataReaderFactory; this is a no-op  // for a shared cache since it'll be cleared by the ApplicationContext.  ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();  } } Copy the code
5.3.2 Judgment on beanDef

The code snippet for the beanDef judgment is as follows:

BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
        ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
    if (logger.isDebugEnabled()) {
        logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
 } } Copy the code

ConfigurationClassUtils defines two constants: private static final String CONFIGURATION_CLASS_FULL = “full” and private static Final String CONFIGURATION_CLASS_LITE = “Lite” These two constants are used to determine whether the current BeanDefinition is a fully or partially configured class. Go in for the Configuration of the @ the Configuration notes here below checkConfigurationClassCandidate judgment, breakpoint debugging validation.

5.3.3 checkConfigurationClassCandidate
public static boolean checkConfigurationClassCandidate(
   BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

    String className = beanDef.getBeanClassName();
    if (className == null|| beanDef.getFactoryMethodName() ! =null) {
 return false;  }   AnnotationMetadata metadata;  if (beanDef instanceof AnnotatedBeanDefinition &&  className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {  / * ** If beanDefinition is an instance of AnnotatedBeanDefinition* and className is the same as the metadata className in beanDefinition* Get metadata from AnnotatedBeanDefinition* /  // Can reuse the pre-parsed metadata from the given BeanDefinition...  metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();  }  else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {  // Check already loaded Class if present...  // since we possibly can't even load the class file for this Class.  / * ** If beanDefinition is an instance of AbstractBeanDefinition* And beanDefinition has a beanClass attribute* instantiation StandardAnnotationMetadata* / Class<? > beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); metadata = new StandardAnnotationMetadata(beanClass, true);  }  else {  try {  MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);  metadata = metadataReader.getAnnotationMetadata();  }  catch (IOException ex) {  if (logger.isDebugEnabled()) {  logger.debug("Could not find class file for introspecting configuration annotations: " +  className, ex);  }  return false;  }  }  /** Determine whether metadata is added@ConfigurationNote * /  if (isFullConfigurationCandidate(metadata)) {  / * ** If present@ConfigurationNote that beanDefinition sets configurationClass to fullSpring considers the class to be a fully annotated class* /  beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);  }  / * ** Determine whether it is added@Import.@Component  * @ImportResource.@ComponentScanannotations* /  else if (isLiteConfigurationCandidate(metadata)) {  / * ** If it doesn't exist@ConfigurationNote that beanDefinition sets configurationClass to LiteSpring considers this class to be a partially annotated class* /  beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);  }  else {  return false;  }   // It's a full or lite configuration candidate... Let's determine the order value, if any.  Integer order = getOrder(metadata);  if(order ! =null) {  beanDef.setAttribute(ORDER_ATTRIBUTE, order);  }   return true; } Copy the code

incheckConfigurationClassCandidateIn the method@ConfigurationAnnotation is the class isAnnotatedBeanDefinitionTo achieve, first get metadatametadataThe diagram below:And then, for theta plus theta@ConfigurationAnnotated class, which sets the class’s property tofull, as shown below:And finally, ifcheckConfigurationClassCandidate()Method returns true, and theBeanDefinitionEncapsulated intoBeanDefinitionHolderAdded to theconfigCandidatesFor later parsing.

5.4 ConfigurationClassParser Instantiated

ConfigurationClassParser parser = new ConfigurationClassParser(
    this.metadataReaderFactory, this.problemReporter, this.environment,
    this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Copy the code

Container formation diagram

No new objects have been added to the IoC container in this article. That’s what this article is about@ConfigurationThe annotation class corresponds to Spring’s built-inConfigurationClassPostProcessorTo deal with.

This article is formatted using MDNICE