Spring Boot【原理分析】(2)——ApplicationContext

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

一、类结构图

20191017100154\_1.png

二、初始化refresh

上文中refresh(context); 会执行AbstractApplicationContext.refresh()。
源码:

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

1.invokeBeanFactoryPostProcessors();
有两个BeanFactoryPostProcessor
20191017100154\_2.png
另外,从BeanFactory中获取BeanDefinitionRegistryPostProcessor
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
20191017100154\_3.png
(1)ConfigurationClassPostProcessor先扫描现有bean中的@Configuration 类,如果为空,将不再继续扫描。如果非空,使用ConfigurationClassParser进行解析。
ConfigurationClassParser源码:

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass);

            // Process any @PropertySource annotations
            for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                    sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {
                if (this.environment instanceof ConfigurableEnvironment) {
                    processPropertySource(propertySource);
                }
                else {
                    logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                            "]. Reason: Environment must implement ConfigurableEnvironment");
                }
            }

            // Process any @ComponentScan annotations
            AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);
            if (componentScan != null && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
                // The config class is annotated with @ComponentScan -> perform the scan immediately
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // Check the set of scanned definitions for any further config classes and parse recursively if necessary
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
                        parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                    }
                }
            }

            // Process any @Import annotations
            processImports(configClass, sourceClass, getImports(sourceClass), true);

            // Process any @ImportResource annotations
            if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
                AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
                String[] resources = importResource.getAliasedStringArray("locations", ImportResource.class, sourceClass);
                Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
                for (String resource : resources) {
                    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                    configClass.addImportedResource(resolvedResource, readerClass);
                }
            }

            // Process individual @Bean methods
            Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
            for (MethodMetadata methodMetadata : beanMethods) {
                configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
            }

            // Process default methods on interfaces
            for (SourceClass ifc : sourceClass.getInterfaces()) {
                beanMethods = ifc.getMetadata().getAnnotatedMethods(Bean.class.getName());
                for (MethodMetadata methodMetadata : beanMethods) {
                    if (!methodMetadata.isAbstract()) {
                        // A default method or other concrete method on a Java 8+ interface...
                        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
                    }
                }
            }

            // Process superclass, if any
            if (sourceClass.getMetadata().hasSuperClass()) {
                String superclass = sourceClass.getMetadata().getSuperClassName();
                if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
                    this.knownSuperclasses.put(superclass, configClass);
                    // Superclass found, return its annotation metadata and recurse
                    return sourceClass.getSuperClass();
                }
            }

            // No superclass -> processing is complete
            return null;
        }

ConfigurationClassParser解析过程
1.子类递归
2.@PropertySource
3.ComponentScanAnnotationParser扫描所有@Component (@Configuration,@Controller,@RestController,@ControllerAdvice,@Repository,@Service)类,递归解析这些类。并注册BeanDefinition。
4.@Import
5.@ImportResource
6.@Bean
7.Interface中的@Bean
8.父类循环解析
上述解析的结果都储存在Set<ConfigurationClass>
(2)ConfigurationClassBeanDefinitionReader解析ConfigurationClass转换为BeanDefinition,包括自身,BeanMethod,@ImportResource,@Import。
XmlBeanDefinitionReader解析@ImportResource的xml文件。并注册BeanDefinition

2.finishBeanFactoryInitialization(beanFactory);
实例化所有bean
构造完一个bean后,会用AutowiredAnnotationBeanPostProcessor检查所有@Autowired依赖属性,并构建相应的bean。
bean装载过程:

  1. 实例化;
  2. 设置属性值;(包括依赖注入)
  3. 如果实现BeanNameAware接口,调用setBeanName设置Bean的ID或者Name;
  4. 如果实现BeanClassLoaderAware接口,调用setBeanClassLoader设置ClassLoader;
  5. 如果实现BeanFactoryAware接口,调用setBeanFactory 设置BeanFactory;
  6. 如果实现ApplicationContextAware,调用setApplicationContext设置ApplicationContext
  7. 调用BeanPostProcessor的预先初始化方法(包含@PostConstruct);
  8. 调用InitializingBean的afterPropertiesSet()方法;
  9. 调用定制init-method方法;
  10. 调用BeanPostProcessor的后初始化方法;AOP代理类通过AspectJAwareAdvisorAutoProxyCreator生成。
    初始化bean源码:
    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            // Aware接口调用 
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 调用BeanPostProcessor.postProcessBeforeInitialization()
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 调用InitializingBean.afterPropertiesSet()
            // 调用自定义init-method
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            // 调用BeanPostProcessor.postProcessAfterInitialization()
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

3.finishRefresh();

调用Lifecycle.start(),更加依赖递归调用start依赖的bean。


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring Boot【原理分析】(2)——ApplicationContext

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏