1.Beanparsing

1.1 Setting the Configuration class processor

1.1.1 Instantiating context objects

public AnnotationConfigServletWebServerApplicationContext(a) {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
Copy the code

1.1.2 instantiationBeanFactory

AnnotationConfigServletWebServerApplicationContex inherited GenericApplicationContext, executed before the constructor in the superclass constructor

public GenericApplicationContext(a) {
    this.beanFactory = new DefaultListableBeanFactory();
}
Copy the code

1.1.3 Instantiating the reader

The reader is instantiated in Section 1.1.1, which injects a series of BeanDefinitions into the container

1.1.4 injectionBeanDefinition

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    if(! registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        / / injection ConfigurationClassPostProcessor, used to handle @ Configuration annotations Configuration class
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if(! registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        / / injection AutowiredAnnotationBeanPostProcessor, Value, used to deal with @autowired, @ @ Inject annotation
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    
    if(jsr250Present && ! registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        / / injection CommonAnnotationBeanPostProcessor, used to handle @ Resource annotation
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    return beanDefs;
}
Copy the code

1.1.5 callBeanFactoryPostProcessors

Context when refresh will perform invokeBeanFactoryPostProcessors () method

public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List
       
         beanFactoryPostProcessors)
        {

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

    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

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

		/ / from the container type BeanDefinitionRegistryPostProcessor Bean name,
        / / in section 1.1.4 injection ConfigurationClassPostProcessor has been realized
        / / BeanDefinitionRegistryPostProcessor and PriorityOrdered interface to meet the conditions
        String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                / / create ConfigurationClassPostProcessor Bean objectcurrentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); }}/ / call ConfigurationClassPostProcessor postProcessBeanDefinitionRegistry () method
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
		/ /... Omit some code}}Copy the code

1.2 Parsing configuration Classes

Methods analytic entrance ConfigurationClassParser doProcessConfigurationClass configuration class

1.2.1 Handling internal configuration classes

if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
	// Handle the Configuration class annotated by the internal @Configuration annotation
    processMemberClasses(configClass, sourceClass, filter);
}
Copy the code

1.2.2 processing@ComponentScanannotations

// Handle @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if(! componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    for (AnnotationAttributes componentScan : componentScans) {
		// Scan the class annotated by the @Component annotation in the specified path and register it as BeanDefinition
        // @controller, @service, @Repository, and @Configuration are all annotated with the @Component annotation
        Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
		/ / traverse BeanDefinition
        for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
                bdCand = holder.getBeanDefinition();
            }
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                // Parse the configuration class annotated by the @Component annotationparse(bdCand.getBeanClassName(), holder.getBeanName()); }}}}Copy the code

1.2.3 processing@Importannotations

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {
    
    for (SourceClass candidate : importCandidates) {
        // 1. If the @import annotation value specifies a class that implements the ImportSelector interface
        if(candidate.isAssignable(ImportSelector.class)) { Class<? > candidateClass = candidate.loadClass();// 1.2 Instantiate objects
            ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                                                                           this.environment, this.resourceLoader, this.registry);
            Predicate<String> selectorFilter = selector.getExclusionFilter();
            if(selectorFilter ! =null) {
                exclusionFilter = exclusionFilter.or(selectorFilter);
            }
            // 1.3 If the DeferredImportSelector interface is implemented, delay processing is performed
            / / @ EnableAutoConfiguration introduce annotations AutoConfigurationImportSelector implements this interface
            // Used to finally load the auto-configuration classes in Spring.Factories
            if (selector instanceof DeferredImportSelector) {
                this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
            }
            // 1.4 If implementing the ImportSelector interface
            else {
                // 1.5 Call the target method
                String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                // 1.6 Recursive invocation
                processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false); }}/ / 2. If the implementation ImportBeanDefinitionRegistrar interface
        else if(candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { Class<? > candidateClass = candidate.loadClass();// 2.1 Instantiate objects
            ImportBeanDefinitionRegistrar registrar =
                ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                                     this.environment, this.resourceLoader, this.registry);
            // 2.2 Store the instantiated object in the current configuration class (used later)
            configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
        }
        else {
            // 3. No interface is implemented, so it is parsed as a common configuration class
            // This common configuration class is introduced by the current configuration class (used later)
            this.importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter); }}}Copy the code

1. To deal with@Beanannotations

// Parse the method with the @bean annotation in the current configuration class and assemble it into MethodMetadata
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
    // Assemble BeanMethod according to MethodMetadata into the current configuration class (we'll use it later)
    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
Copy the code

1.2.5 processing@EnableAutoConfigurationannotations

After all configuration classes are parsed, they are put into the map

this.configurationClasses.put(configClass, configClass);
Copy the code

@ EnableAutoConfiguration introduced AutoConfigurationImportSelector AutoConfigurationImportSelector and implements DeferredImportSelector interface, According to the analysis of could discern AutoConfigurationImportSelector 1.2.3 chapter introduced the automatic configuration of class will be in the final parse, join configurationClasses container after parsing is complete

1.2.6 loadBeanDefinition

@import, @Bean, and @EnableAutoConfiguration do not generate a BeanDefinition injection container except for the @ComponentScan annotation scanned configuration class in Section 1.2.2

private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
	// If the current configuration class is imported, generate BeanDefinition and inject it into the container, as described in Section 1.2.3
    if (configClass.isImported()) {
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    
    // Get the BeanMethod in the current configuration class, generate the BeanDefinition, and inject it into the container, as shown in Section 1.2.4
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }

    / / get the current configuration class ImportBeanDefinitionRegistrar BeanDefinition and injected into the container, corresponding 1.2.3 section in the second part
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
Copy the code

1.2.7 Several ways to inject containers

  • @Componentannotations
  • @ImportThe introduction of
  • @Beanannotations
  • inspring.factoriesDefined in theorg.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx

2.Beancreate

After the configuration class is parsed to generate a BeanDefinition and injected into the container, the next step is to instantiate the BeanDefinition in the container

2.1 Beaninstantiation

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.Class<? > beanClass = resolveBeanClass(mbd, beanName);// 1. Instantiate with the supplied SupplierSupplier<? > instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier ! =null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // 2.@Bean annotation annotation, instantiated by calling the target method reflectively
    if(mbd.getFactoryMethodName() ! =null) {
        returninstantiateUsingFactoryMethod(beanName, mbd, args); } Constructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {// 3. Call the constructor to instantiate
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    ctors = mbd.getPreferredConstructors();
    if(ctors ! =null) {
        // 4. Call the constructor to instantiate
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // 5. Call the no-argument constructor to instantiate
    return instantiateBean(beanName, mbd);
}
Copy the code

2.2 the fillingBean

After the object is instantiated, it needs to fill in the injected properties, such as @Value, @AutoWired, and @Inject annotated properties or methods

2.2.1 Specifying the fill type

public AutowiredAnnotationBeanPostProcessor(a) {
    // 1. Set @autowired
    this.autowiredAnnotationTypes.add(Autowired.class);
    // 2. Set the @value type
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        // 3. Support @inject type
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                                          ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
    }
    catch (ClassNotFoundException ex) {
    }
}
Copy the code

2.2.2 Building metadata

private InjectionMetadata buildAutowiringMetadata(finalClass<? > clazz) {
    if(! AnnotationUtils.isCandidateClass(clazz,this.autowiredAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }

    List<InjectionMetadata.InjectedElement> elements = newArrayList<>(); Class<? > targetClass = clazz;do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
		Construct AutowiredFieldElement by iterating over the attributes annotated by @Value, @AutoWired, and @Inject annotationsReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<? > ann = findAutowiredAnnotation(field);if(ann ! =null) {
                // 2. Cannot be modified static
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                currElements.add(newAutowiredFieldElement(field, required)); }});// 3. Construct AutowiredMethodElement by iterating the method annotated by @Value, @AutoWired, @Inject annotation
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if(! BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return; } MergedAnnotation<? > ann = findAutowiredAnnotation(bridgedMethod);if(ann ! =null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                // 4. Cannot be modified static
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                if (method.getParameterCount() == 0) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation should only be used on methods with parameters: "+ method); }}boolean required = determineRequiredStatus(ann);
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                currElements.add(newAutowiredMethodElement(method, required, pd)); }}); elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while(targetClass ! =null&& targetClass ! = Object.class);return InjectionMetadata.forElements(elements, clazz);
}
Copy the code

2.2.3 Injecting padding

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements ! =null ? checkedElements : this.injectedElements);
    if(! elementsToIterate.isEmpty()) {// 1. Iterate over the metadata constructed in Section 2.2.2
        for (InjectedElement element : elementsToIterate) {
            // 2. If the annotation is @value, the corresponding configuration is obtained from the Environment based on the Value of the Value attribute
            // 3. If the @autoWired annotation annotation is annotated, the corresponding Bean is fetched from the container for injectionelement.inject(target, beanName, pvs); }}}Copy the code

2.3 the initializationBean

2.3.1 AwareTo deal with

private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        // 1. If the current Bean implements the BeanNameAware interface, the setBeanName() method is called to set the Bean name
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        // 2. The current Bean implements the BeanClassLoaderAware interface, so the setBeanClassLoader() method is called to set the ClassLoader
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if(bcl ! =null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); }}// 3. If the current Bean implements the BeanFactoryAware interface, the setBeanFactory() method is called to set the BeanFactory
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); }}}Copy the code

ApplicationContextAwareProcessor preposition

private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }
    if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    if (bean instanceof ApplicationStartupAware) {
        ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
    }
    if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); }}Copy the code

Here you can understand why the implementation of xxxAware interface, you can get a certain ability of the reason

2.3.2 BeanPostProcessorpre-processing

All of the traversal container BeanPostProcessor and call its postProcessBeforeInitialization () method

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
Copy the code

2.3.3 @PostConstructAnnotation processing

CommonAnnotationBeanPostProcessor implements the BeanPostProcessor interface, therefore also call BeanPostProcessor postProcessBeforeInitialization () method, Used to handle @postconstruct annotations

public CommonAnnotationBeanPostProcessor(a) {
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    setInitAnnotationType(PostConstruct.class);
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}
Copy the code

2.3.4 InitializingBeanTo deal with

The Bean implements the InitializingBean interface and calls the afterPropertiesSet() implementation method to initialize the Bean

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } ((InitializingBean) bean).afterPropertiesSet(); }}Copy the code

2.3.5 @BeanThe initMethod annotation is handled

if(mbd ! =null&& bean.getClass() ! = NullBean.class) { String initMethodName = mbd.getInitMethodName();if(StringUtils.hasLength(initMethodName) && ! (isInitializingBean &&"afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) {// Find the initialization method specified by initMethod in the Bean and call backinvokeCustomInitMethod(beanName, bean, mbd); }}Copy the code

2.3.6 BeanPostProcessorPost processing

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
Copy the code

3. BeanLife cycle summary

  • Parsing generatedBeanDefinitionInto the container
  • createBean
  • fill@Valueand@Autowireddata
  • The callbackAwareInterface implementation method
  • performBeanPostProcessorpre-processing
  • The callbackInitializingBeanInterface implementation method
  • call@BeanThe method specified by the initMethod property of the annotation
  • performBeanPostProcessorPost processing