springboot系列之启动流程
Springboot简介
springboot封装了Spring组件,基于约定优于配置。提升了开发效率,本文主要讲解springboot框架的启动过程。
启动流程分析
1、首先,我们看一下启动类SpringApplication,它是位于org.springframework.boot包下面的。项目启动类源码
1@SpringBootApplication 2public class Application { 3 4 public static void main(String[] args) { 5 SpringApplication.run(Application.class, args); 6 } 7 8}
这里用到了SpringBootApplication注解,然后在main方法中启动boot应用。
2、我们接下来看看SpringBootApplication注解的源码
1@Target(ElementType.TYPE) 2@Retention(RetentionPolicy.RUNTIME) 3@Documented 4@Inherited 5@SpringBootConfiguration 6@EnableAutoConfiguration 7@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 8 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 9public @interface SpringBootApplication { 10 /** 11 * Exclude specific auto-configuration classes such that they will never be applied. 12 * @return the classes to exclude 13 */ 14 @AliasFor(annotation = EnableAutoConfiguration.class) 15 Class<!--?-->[] exclude() default {}; 16 /** 17 * Exclude specific auto-configuration class names such that they will never be 18 * applied. 19 * @return the class names to exclude 20 * @since 1.3.0 21 */ 22 @AliasFor(annotation = EnableAutoConfiguration.class) 23 String[] excludeName() default {}; 24 /** 25 * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses} 26 * for a type-safe alternative to String-based package names. 27 * @return base packages to scan 28 * @since 1.3.0 29 */ 30 @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") 31 String[] scanBasePackages() default {}; 32 /** 33 * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to 34 * scan for annotated components. The package of each class specified will be scanned. 35 * <p> 36 * Consider creating a special no-op marker class or interface in each package that 37 * serves no purpose other than being referenced by this attribute. 38 * @return base packages to scan 39 * @since 1.3.0 40 */ 41 @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") 42 Class<!--?-->[] scanBasePackageClasses() default {}; 43}
它是位于org.springframework.boot.autoconfigure包下面的。我们可以看到它依赖了几个重要的注解SpringBootConfiguration、EnableAutoConfiguration、ComponentScan这三个注解。其中EnableAutoConfiguration就是springboot自动配置用到的类,在接下来我们将会重点介绍。
3、我们在看SpringApplication运行的run方法
1 /** 2 * Static helper that can be used to run a {@link SpringApplication} from the 3 * specified sources using default settings and user supplied arguments. 4 * @param primarySources the primary sources to load 5 * @param args the application arguments (usually passed from a Java main method) 6 * @return the running {@link ApplicationContext} 7 */ 8 public static ConfigurableApplicationContext run(Class<!--?-->[] primarySources, String[] args) { 9 return new SpringApplication(primarySources).run(args); 10 }
首先,创建SpringApplication应用对象,然后调用run方法传入启动参数
1 public SpringApplication(ResourceLoader resourceLoader, Class<!--?-->... primarySources) { 2 this.resourceLoader = resourceLoader; 3 Assert.notNull(primarySources, "PrimarySources must not be null"); 4 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); 5 this.webApplicationType = WebApplicationType.deduceFromClasspath(); 6 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); 7 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); 8 this.mainApplicationClass = deduceMainApplicationClass(); 9 } 10 11 12 this.webApplicationType = WebApplicationType.deduceFromClasspath(); 13 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); 14 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); 15 this.mainApplicationClass = deduceMainApplicationClass();
这是创建对象的方法,先校验启动类,然后调用deduceFromClasspath方法推断一个应用类型(是否是web项目)初始化工厂类,设置Spring监听器(观察者模式)。
4、创建好对象后,我们接着看run方法
1/** 2 * Run the Spring application, creating and refreshing a new 3 * {@link ApplicationContext}. 4 * @param args the application arguments (usually passed from a Java main method) 5 * @return a running {@link ApplicationContext} 6 */ 7 public ConfigurableApplicationContext run(String... args) { 8 //开启系统启动时间监听 9 StopWatch stopWatch = new StopWatch(); 10 stopWatch.start(); 11 ConfigurableApplicationContext context = null; 12 //创建一场报告集合 13 Collection<springbootexceptionreporter> exceptionReporters = new ArrayList<>(); 14 //配置检测无显示器也可以启动 15 configureHeadlessProperty(); 16 //获取运行监听器,获取事件发布监听 17 SpringApplicationRunListeners listeners = getRunListeners(args); 18 //启动监听器 19 listeners.starting(); 20 try { 21 //通过启动参数构建应用参数 22 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 23 //创建上线文环境 24 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 25 //配置忽略的bean信息 26 configureIgnoreBeanInfo(environment); 27 //打印boot启动logo 28 Banner printedBanner = printBanner(environment); 29 //创建上线文(容器) 30 context = createApplicationContext(); 31 //获取异常集合 32 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, 33 new Class[] { ConfigurableApplicationContext.class }, context); 34 //准备上下文 35 prepareContext(context, environment, listeners, applicationArguments, printedBanner); 36 //刷新上下文(重点) 37 refreshContext(context); 38 //刷新之后 39 afterRefresh(context, applicationArguments); 40 //关闭系统时间监听 41 stopWatch.stop(); 42 //打印日志 43 if (this.logStartupInfo) { 44 new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); 45 } 46 listeners.started(context); 47 callRunners(context, applicationArguments); 48 } 49 catch (Throwable ex) { 50 handleRunFailure(context, ex, exceptionReporters, listeners); 51 throw new IllegalStateException(ex); 52 } 53 54 try { 55 listeners.running(context); 56 } 57 catch (Throwable ex) { 58 handleRunFailure(context, ex, exceptionReporters, null); 59 throw new IllegalStateException(ex); 60 } 61 return context; 62 }
我们只看几个重要的方法,首先看createApplicationContext()创建上下文(容器)方法
1 /** 2 * Strategy method used to create the {@link ApplicationContext}. By default this 3 * method will respect any explicitly set application context or application context 4 * class before falling back to a suitable default. 5 * @return the application context (not yet refreshed) 6 * @see #setApplicationContextClass(Class) 7 */ 8 protected ConfigurableApplicationContext createApplicationContext() { 9 //获取启动类 10 Class<!--?--> contextClass = this.applicationContextClass; 11 //推断上下文类型,默认web类型, 12 if (contextClass == null) { 13 try { 14 switch (this.webApplicationType) { 15 case SERVLET: 16 contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); 17 break; 18 //flux类型上下文 19 case REACTIVE: 20 contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); 21 break; 22 default: 23 contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); 24 } 25 } 26 catch (ClassNotFoundException ex) { 27 throw new IllegalStateException( 28 "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", 29 ex); 30 } 31 } 32 //实例化上下文,容器 33 return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); 34 }
我们在看,prepareContext(context, environment, listeners, applicationArguments, printedBanner);准备上下文方法
1 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, 2 SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { 3 //设置上下文环境 4 context.setEnvironment(environment); 5 //处理应用上下文 6 postProcessApplicationContext(context); 7 //应用初始化类 8 applyInitializers(context); 9 //监听器准备上下文 10 listeners.contextPrepared(context); 11 if (this.logStartupInfo) { 12 logStartupInfo(context.getParent() == null); 13 logStartupProfileInfo(context); 14 } 15 // Add boot specific singleton beans 16 //创建bean工厂 17 ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); 18 //注册应用参数bean 19 beanFactory.registerSingleton("springApplicationArguments", applicationArguments); 20 if (printedBanner != null) { 21 beanFactory.registerSingleton("springBootBanner", printedBanner); 22 } 23 if (beanFactory instanceof DefaultListableBeanFactory) { 24 ((DefaultListableBeanFactory) beanFactory) 25 .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); 26 } 27 // Load the sources 28 Set<object> sources = getAllSources(); 29 Assert.notEmpty(sources, "Sources must not be empty"); 30 load(context, sources.toArray(new Object[0])); 31 listeners.contextLoaded(context); 32 }
在看、重要的refreshContext(context);刷新上下文方法重点
1 private void refreshContext(ConfigurableApplicationContext context) { 2 refresh(context); 3 if (this.registerShutdownHook) { 4 try { 5 context.registerShutdownHook(); 6 } 7 catch (AccessControlException ex) { 8 // Not allowed in some environments. 9 } 10 } 11 }
点进去refresh(context);方法进入
1 /** 2 * Refresh the underlying {@link ApplicationContext}. 3 * @param applicationContext the application context to refresh 4 */ 5 protected void refresh(ApplicationContext applicationContext) { 6 Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); 7 ((AbstractApplicationContext) applicationContext).refresh(); 8 }
类型转换为AbstractApplicationContext,继续看refresh方法
1@Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 //准备刷新 5 prepareRefresh(); 6 // 刷新子类工厂 7 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 8 // 准备beanFactory 9 prepareBeanFactory(beanFactory); 10 try { 11 // 处理bean工厂 12 postProcessBeanFactory(beanFactory); 13 // 调用bean共产处理器重点 14 invokeBeanFactoryPostProcessors(beanFactory); 15 // 注册bean工厂处理器 16 registerBeanPostProcessors(beanFactory); 17 // 初始化消息类 18 initMessageSource(); 19 // 初始化应用事件广播 20 initApplicationEventMulticaster(); 21 // 正在刷新的 22 onRefresh(); 23 // 发布事件监听器 24 registerListeners(); 25 // 完成bean工厂注册 26 finishBeanFactoryInitialization(beanFactory); 27 // 完成事件刷新 28 finishRefresh(); 29 } 30 catch (BeansException ex) { 31 if (logger.isWarnEnabled()) { 32 logger.warn("Exception encountered during context initialization - " + 33 "cancelling refresh attempt: " + ex); 34 } 35 36 // Destroy already created singletons to avoid dangling resources. 37 destroyBeans(); 38 39 // Reset 'active' flag. 40 cancelRefresh(ex); 41 42 // Propagate exception to caller. 43 throw ex; 44 } 45 46 finally { 47 // Reset common introspection caches in Spring's core, since we 48 // might not ever need metadata for singleton beans anymore... 49 resetCommonCaches(); 50 } 51 } 52 } 53
我们在看prepareRefresh准备刷新方法
1/** 2 * Prepare this context for refreshing, setting its startup date and 3 * active flag as well as performing any initialization of property sources. 4 */ 5 protected void prepareRefresh() { 6 // 启动应用开关 7 this.startupDate = System.currentTimeMillis(); 8 this.closed.set(false); 9 //设置启动状态 10 this.active.set(true); 11 if (logger.isDebugEnabled()) { 12 if (logger.isTraceEnabled()) { 13 logger.trace("Refreshing " + this); 14 } 15 else { 16 logger.debug("Refreshing " + getDisplayName()); 17 } 18 } 19 20 // 初始化属性类 21 initPropertySources(); 22 // 校验属性 23 // see ConfigurablePropertyResolver#setRequiredProperties 24 getEnvironment().validateRequiredProperties(); 25 // Store pre-refresh ApplicationListeners... 26 if (this.earlyApplicationListeners == null) { 27 this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); 28 } 29 else { 30 // Reset local application listeners to pre-refresh state. 31 this.applicationListeners.clear(); 32 this.applicationListeners.addAll(this.earlyApplicationListeners); 33 } 34 35 // Allow for the collection of early ApplicationEvents, 36 // to be published once the multicaster is available... 37 this.earlyApplicationEvents = new LinkedHashSet<>(); 38 } 39
在看prepareBeanFactory准备配置工厂方法
1/** 2 * Configure the factory's standard context characteristics, 3 * such as the context's ClassLoader and post-processors. 4 * @param beanFactory the BeanFactory to configure 5 */ 6 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { 7 // 设置类加载器 8 beanFactory.setBeanClassLoader(getClassLoader()); 9 //设置bean表达式处理 10 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); 11 //设置属性编辑器注册 12 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); 13 14 // 配置bean处理器,后置处理 15 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 16 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); 17 beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); 18 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 19 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 20 beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 21 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 22 23 // BeanFactory interface not registered as resolvable type in a plain factory. 24 // MessageSource registered (and found for autowiring) as a bean. 25 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); 26 beanFactory.registerResolvableDependency(ResourceLoader.class, this); 27 beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); 28 beanFactory.registerResolvableDependency(ApplicationContext.class, this); 29 30 // 添加事件监听处理器 31 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); 32 33 // Detect a LoadTimeWeaver and prepare for weaving, if found. 34 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { 35 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); 36 // Set a temporary ClassLoader for type matching. 37 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); 38 } 39 40 // Register default environment beans. 41 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { 42 //注册环境bean beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); 43 } 44 if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { 45 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); 46 } 47 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { 48 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); 49 } 50 }
在看postProcessBeanFactory(beanFactory);处理工厂类(子类)
1在ServletWebServerApplicationContext类中实现了这个方法 2 @Override 3 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 4 beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); 5 beanFactory.ignoreDependencyInterface(ServletContextAware.class); 6 registerWebApplicationScopes(); 7 }
在看invokeBeanFactoryPostProcessors(beanFactory);调用bean工厂处理器方法
1 /** 2 * Instantiate and invoke all registered BeanFactoryPostProcessor beans, 3 * respecting explicit order if given. 4 * <p>Must be called before singleton instantiation. 5 */ 6 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { 7//处理工厂类代表 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); 8 9 // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime 10 // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) 11 if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { 12 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); 13 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); 14 } 15 }
点进去看看
1public static void invokeBeanFactoryPostProcessors( 2 ConfigurableListableBeanFactory beanFactory, List<beanfactorypostprocessor> beanFactoryPostProcessors) { 3 4 // Invoke BeanDefinitionRegistryPostProcessors first, if any. 5 Set<string> processedBeans = new HashSet<>(); 6 7 if (beanFactory instanceof BeanDefinitionRegistry) { 8 BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; 9 List<beanfactorypostprocessor> regularPostProcessors = new ArrayList<>(); 10 List<beandefinitionregistrypostprocessor> registryProcessors = new ArrayList<>(); 11 12 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { 13 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { 14 BeanDefinitionRegistryPostProcessor registryProcessor = 15 (BeanDefinitionRegistryPostProcessor) postProcessor; 16 registryProcessor.postProcessBeanDefinitionRegistry(registry); 17 registryProcessors.add(registryProcessor); 18 } 19 else { 20 regularPostProcessors.add(postProcessor); 21 } 22 } 23 24 // Do not initialize FactoryBeans here: We need to leave all regular beans 25 // uninitialized to let the bean factory post-processors apply to them! 26 // Separate between BeanDefinitionRegistryPostProcessors that implement 27 // PriorityOrdered, Ordered, and the rest. 28 List<beandefinitionregistrypostprocessor> currentRegistryProcessors = new ArrayList<>(); 29 30 // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. 31 String[] postProcessorNames = 32 beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 33 for (String ppName : postProcessorNames) { 34 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 35 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 36 processedBeans.add(ppName); 37 } 38 } 39 sortPostProcessors(currentRegistryProcessors, beanFactory); 40 registryProcessors.addAll(currentRegistryProcessors); 41 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 42 currentRegistryProcessors.clear(); 43 44 // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. 45 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 46 for (String ppName : postProcessorNames) { 47 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { 48 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 49 processedBeans.add(ppName); 50 } 51 } 52 sortPostProcessors(currentRegistryProcessors, beanFactory); 53 registryProcessors.addAll(currentRegistryProcessors); 54 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 55 currentRegistryProcessors.clear(); 56 57 // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. 58 boolean reiterate = true; 59 while (reiterate) { 60 reiterate = false; 61 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 62 for (String ppName : postProcessorNames) { 63 if (!processedBeans.contains(ppName)) { 64 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 65 processedBeans.add(ppName); 66 reiterate = true; 67 } 68 } 69 sortPostProcessors(currentRegistryProcessors, beanFactory); 70 registryProcessors.addAll(currentRegistryProcessors); 71 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 72 currentRegistryProcessors.clear(); 73 } 74 75 // Now, invoke the postProcessBeanFactory callback of all processors handled so far. 76 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); 77 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); 78 } 79 80 else { 81 // Invoke factory processors registered with the context instance. 82 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); 83 } 84 85 // Do not initialize FactoryBeans here: We need to leave all regular beans 86 // uninitialized to let the bean factory post-processors apply to them! 87 String[] postProcessorNames = 88 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); 89 90 // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, 91 // Ordered, and the rest. 92 List<beanfactorypostprocessor> priorityOrderedPostProcessors = new ArrayList<>(); 93 List<string> orderedPostProcessorNames = new ArrayList<>(); 94 List<string> nonOrderedPostProcessorNames = new ArrayList<>(); 95 for (String ppName : postProcessorNames) { 96 if (processedBeans.contains(ppName)) { 97 // skip - already processed in first phase above 98 } 99 else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 100 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); 101 } 102 else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { 103 orderedPostProcessorNames.add(ppName); 104 } 105 else { 106 nonOrderedPostProcessorNames.add(ppName); 107 } 108 } 109 110 // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. 111 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 112 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); 113 114 // Next, invoke the BeanFactoryPostProcessors that implement Ordered. 115 List<beanfactorypostprocessor> orderedPostProcessors = new ArrayList<>(); 116 for (String postProcessorName : orderedPostProcessorNames) { 117 orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); 118 } 119 sortPostProcessors(orderedPostProcessors, beanFactory); 120 invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); 121 122 // Finally, invoke all other BeanFactoryPostProcessors. 123 List<beanfactorypostprocessor> nonOrderedPostProcessors = new ArrayList<>(); 124 for (String postProcessorName : nonOrderedPostProcessorNames) { 125 nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); 126 } 127 invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); 128 129 // Clear cached merged bean definitions since the post-processors might have 130 // modified the original metadata, e.g. replacing placeholders in values... 131 beanFactory.clearMetadataCache(); 132 }
点进去invokeBeanFactoryPostProcessors方法
1 /** 2 * Invoke the given BeanFactoryPostProcessor beans. 3 */ 4 private static void invokeBeanFactoryPostProcessors( 5 Collection<!--? extends BeanFactoryPostProcessor--> postProcessors, ConfigurableListableBeanFactory beanFactory) { 6 7 for (BeanFactoryPostProcessor postProcessor : postProcessors) { 8 postProcessor.postProcessBeanFactory(beanFactory); 9 } 10 }
点击postProcessBeanFactory(beanFactory);找到实现类
1 @Override 2 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 3 int factoryId = System.identityHashCode(beanFactory); 4 if (this.factoriesPostProcessed.contains(factoryId)) { 5 throw new IllegalStateException( 6 "postProcessBeanFactory already called on this post-processor against " + beanFactory); 7 } 8 this.factoriesPostProcessed.add(factoryId); 9 if (!this.registriesPostProcessed.contains(factoryId)) { 10 // BeanDefinitionRegistryPostProcessor hook apparently not supported... 11 // Simply call processConfigurationClasses lazily at this point then. 12 processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); 13 } 14 15 enhanceConfigurationClasses(beanFactory); 16 beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); 17 }
点击processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);方法找到
1// Parse each @Configuration class 2 ConfigurationClassParser parser = new ConfigurationClassParser( 3 this.metadataReaderFactory, this.problemReporter, this.environment, 4 this.resourceLoader, this.componentScanBeanNameGenerator, registry); 5 6 Set<beandefinitionholder> candidates = new LinkedHashSet<>(configCandidates); 7 Set<configurationclass> alreadyParsed = new HashSet<>(configCandidates.size()); 8 do { 9 parser.parse(candidates); 10 parser.validate(); 11 12 Set<configurationclass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); 13 configClasses.removeAll(alreadyParsed);
继续找parse方法,找到ConfigurationClassParser类这个方法,接着找
1 @Nullable 2 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) 3 throws IOException {
// Process any @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), true);
1 // Process any @ImportResource annotations 2 AnnotationAttributes importResource = 3 AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); 4 if (importResource != null) { 5 String[] resources = importResource.getStringArray("locations"); 6 Class<!--? extends BeanDefinitionReader--> readerClass = importResource.getClass("reader"); 7 for (String resource : resources) { 8 String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); 9 configClass.addImportedResource(resolvedResource, readerClass); 10 } 11 } 12 13 // Process individual [@Bean](https://my.oschina.net/bean) methods 14 Set<methodmetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); 15 for (MethodMetadata methodMetadata : beanMethods) { 16 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); 17 } 18 19 // Process default methods on interfaces 20 processInterfaces(configClass, sourceClass); 21 22 // Process superclass, if any 23 if (sourceClass.getMetadata().hasSuperClass()) { 24 String superclass = sourceClass.getMetadata().getSuperClassName(); 25 if (superclass != null && !superclass.startsWith("java") && 26 !this.knownSuperclasses.containsKey(superclass)) { 27 this.knownSuperclasses.put(superclass, configClass); 28 // Superclass found, return its annotation metadata and recurse 29 return sourceClass.getSuperClass(); 30 } 31 } 32 33 // No superclass -> processing is complete 34 return null; 35 36 37我们找到processImports的处理地方 38 39 40this.importStack.push(configClass); 41 try { 42 for (SourceClass candidate : importCandidates) { 43 if (candidate.isAssignable(ImportSelector.class)) { 44 // Candidate class is an ImportSelector -> delegate to it to determine imports 45 Class<!--?--> candidateClass = candidate.loadClass(); 46 ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); 47 ParserStrategyUtils.invokeAwareMethods( 48 selector, this.environment, this.resourceLoader, this.registry); 49 if (selector instanceof DeferredImportSelector) { 50 this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); 51 } 52 else { 53 String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); 54 Collection<sourceclass> importSourceClasses = asSourceClasses(importClassNames); 55 processImports(configClass, currentSourceClass, importSourceClasses, false); 56 } 57 } 58 else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { 59 // Candidate class is an ImportBeanDefinitionRegistrar -> 60 // delegate to it to register additional bean definitions 61 Class<!--?--> candidateClass = candidate.loadClass(); 62 ImportBeanDefinitionRegistrar registrar = 63 BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); 64 ParserStrategyUtils.invokeAwareMethods( 65 registrar, this.environment, this.resourceLoader, this.registry); 66 configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); 67 } 68 else { 69 // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> 70 // process it as an [@Configuration](https://my.oschina.net/pointdance) class 71 this.importStack.registerImport( 72 currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); 73 processConfigurationClass(candidate.asConfigClass(configClass)); 74 } 75 } 76 } 77 78 79ImportSelector接口处理的地方,自动配置外部bean的方法 80 81接下来,看registerBeanPostProcessors(beanFactory);注册bean处理器工厂 82 83然后,看onRefresh方法 84 85 86[@Override](https://my.oschina.net/u/1162528) 87protected void onRefresh() { 88 super.onRefresh(); 89 try { 90 createWebServer(); 91 } 92 catch (Throwable ex) { 93 throw new ApplicationContextException("Unable to start web server", ex); 94 } 95} 96 97 98在这里创建web容器 99完成刷新,应用启动完成,还有细节结下来在细说。
有问题,请留言! 个人博客地址</sourceclass></methodmetadata></configurationclass></configurationclass></beandefinitionholder></beanfactorypostprocessor></beanfactorypostprocessor></string></string></beanfactorypostprocessor></beandefinitionregistrypostprocessor></beandefinitionregistrypostprocessor></beanfactorypostprocessor></string></beanfactorypostprocessor></p></object></springbootexceptionreporter></p>