一.源码分析
1.创建ApplicationContext
在上面spring boot启动中的分析中,发现在SpringApplication.run中创建了ApplicationContext 并且在context = this.createApplicationContext();中创建上下文。
1. public ConfigurableApplicationContext run(String... args) { 2. StopWatch stopWatch = new StopWatch(); 3. stopWatch.start(); 4. ConfigurableApplicationContext context = null; 5. Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); 6. this.configureHeadlessProperty(); 7. SpringApplicationRunListeners listeners = this.getRunListeners(args); 8. listeners.starting(); 9. 10. Collection exceptionReporters; 11. try { 12. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 13. ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); 14. this.configureIgnoreBeanInfo(environment); 15. Banner printedBanner = this.printBanner(environment); 16. //创建spring上下文 17. context = this.createApplicationContext(); 18. exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); 19. this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); 20. //注入bean 21. this.refreshContext(context); 22. this.afterRefresh(context, applicationArguments); 23. stopWatch.stop(); 24. if (this.logStartupInfo) { 25. (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); 26. } 27. 28. listeners.started(context); 29. this.callRunners(context, applicationArguments); 30. } catch (Throwable var10) { 31. this.handleRunFailure(context, var10, exceptionReporters, listeners); 32. throw new IllegalStateException(var10); 33. } 34. 35. try { 36. listeners.running(context); 37. return context; 38. } catch (Throwable var9) { 39. this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); 40. throw new IllegalStateException(var9); 41. } 42. }
其中创建的ApplicationContext类型如下,创建的类型为AnnotationConfigServletWebServerApplicationContext,所以ioc我们可以将断点打在AnnotationConfigApplicationContext中。
1. protected ConfigurableApplicationContext createApplicationContext() { 2. Class<?> contextClass = this.applicationContextClass; 3. if (contextClass == null) { 4. try { 5. switch(this.webApplicationType) { 6. case SERVLET: 7. contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"); 8. break; 9. case REACTIVE: 10. contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"); 11. break; 12. default: 13. contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext"); 14. } 15. } catch (ClassNotFoundException var3) { 16. throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3); 17. } 18. } 19. 20. return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass); 21. }
2 进入AbstractApplicationContext的refresh()方法
在refreshContext最终会调用AbstractApplicationContext的refresh方法。
this.refreshContext(context);
1. @Override 2. public void refresh() throws BeansException, IllegalStateException { 3. synchronized (this.startupShutdownMonitor) { 4. // Prepare this context for refreshing. 5. //刷新上下文环境 6. prepareRefresh(); 7. // Tell the subclass to refresh the internal bean factory. 8. //这里是在子类中启动 refreshBeanFactory() 的地方 9. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 10. // Prepare the bean factory for use in this context. 11. //准备bean工厂,以便在此上下文中使用 12. prepareBeanFactory(beanFactory); 13. try { 14. // Allows post-processing of the bean factory in context subclasses. 15. //设置 beanFactory 的后置处理 16. postProcessBeanFactory(beanFactory); 17. // Invoke factory processors registered as beans in the context. 18. //调用 BeanFactory 的后处理器,这些处理器是在Bean 定义中向容器注册的 19. invokeBeanFactoryPostProcessors(beanFactory); 20. // Register bean processors that intercept bean creation. 21. //注册Bean的后处理器,在Bean创建过程中调用 22. registerBeanPostProcessors(beanFactory); 23. // Initialize message source for this context. 24. //对上下文中的消息源进行初始化 25. initMessageSource(); 26. // Initialize event multicaster for this context. 27. //初始化上下文中的事件机制 28. initApplicationEventMulticaster(); 29. // Initialize other special beans in specific context subclasses. 30. //初始化其他特殊的Bean 31. onRefresh(); 32. // Check for listener beans and register them. 33. //检查监听Bean并且将这些监听Bean向容器注册 34. registerListeners(); 35. // Instantiate all remaining (non-lazy-init) singletons. 36. //实例化所有的(non-lazy-init)单件 37. finishBeanFactoryInitialization(beanFactory); 38. // Last step: publish corresponding event. 39. //发布容器事件,结束Refresh过程 40. finishRefresh(); 41. } catch (BeansException ex) { 42. if (logger.isWarnEnabled()) { 43. logger.warn("Exception encountered during context initialization - " + 44. "cancelling refresh attempt: " + ex); 45. } 46. // Destroy already created singletons to avoid dangling resources. 47. destroyBeans(); 48. // Reset 'active' flag. 49. cancelRefresh(ex); 50. // Propagate exception to caller. 51. throw ex; 52. } finally { 53. // Reset common introspection caches in Spring's core, since we 54. // might not ever need metadata for singleton beans anymore... 55. resetCommonCaches(); 56. } 57. } 58. }
1.this.obtainFreshBeanFactory();装载初始化的bean
1. protected final void refreshBeanFactory() throws BeansException { 2. if (this.hasBeanFactory()) { 3. this.destroyBeans(); 4. this.closeBeanFactory(); 5. } 6. 7. try { 8. //创建BeanFactory 9. DefaultListableBeanFactory beanFactory = this.createBeanFactory(); 10. beanFactory.setSerializationId(this.getId()); 11. this.customizeBeanFactory(beanFactory); 12. //载入bean 13. this.loadBeanDefinitions(beanFactory); 14. synchronized(this.beanFactoryMonitor) { 15. this.beanFactory = beanFactory; 16. } 17. } catch (IOException var5) { 18. throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5); 19. } 20. } 21. 22. 23. 24.
2.this.prepareBeanFactory(beanFactory);
1. protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { 2. //添加类加载器 3. beanFactory.setBeanClassLoader(this.getClassLoader()); 4. // 配置EL表达式 5. beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); 6. // 添加属性编辑器 PropertyEditor 7. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment())); 8. //添加后置处理器 9. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 10. 11. //忽略以下类 12. beanFactory.ignoreDependencyInterface(EnvironmentAware.class); 13. beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); 14. beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 15. beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 16. beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 17. beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 18. 19. //放入resolvableDependencies属性 20. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); 21. beanFactory.registerResolvableDependency(ResourceLoader.class, this); 22. beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); 23. beanFactory.registerResolvableDependency(ApplicationContext.class, this); 24. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); 25. if (beanFactory.containsBean("loadTimeWeaver")) { 26. beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); 27. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); 28. } 29. 30. //以下为单例 31. if (!beanFactory.containsLocalBean("environment")) { 32. beanFactory.registerSingleton("environment", this.getEnvironment()); 33. } 34. 35. if (!beanFactory.containsLocalBean("systemProperties")) { 36. beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties()); 37. } 38. 39. if (!beanFactory.containsLocalBean("systemEnvironment")) { 40. beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment()); 41. } 42. 43. }
3.postProcessBeanFactory
postProcessBeanFactory()方法向上下文中添加了一系列的Bean的后置处理器。后置处理器工作的时机是在所有的beanDenifition加载完成之后,bean实例化之前执行。简单来说Bean的后置处理器可以修改BeanDefinition的属性信息。
4.invokeBeanFactoryPostProcessors-->parse
1. public void refresh() throws BeansException, IllegalStateException { 2. ... 3. this.invokeBeanFactoryPostProcessors(beanFactory); 4. ... 5. } 6. 7. 8. 9. protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { 10. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors()); 11. ... 12. 13. } 14. 15. 16. public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { 17. ... 18. 19. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 20. currentRegistryProcessors.clear(); 21. ... 22. } 23. 24. 25. private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, 26. ... 27. 28. postProcessor.postProcessBeanDefinitionRegistry(registry); 29. 30. 31. } 32. 33. 34. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 35. ... 36. this.processConfigBeanDefinitions(registry); 37. ... 38. } 39. 40. 41. public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { 42. ... 43. parser.parse(candidates); 44. ... 45. }
1. // ConfigurationClassParser类 2. public void parse(Set<BeanDefinitionHolder> configCandidates) { 3. Iterator var2 = configCandidates.iterator(); 4. 5. while(var2.hasNext()) { 6. BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next(); 7. BeanDefinition bd = holder.getBeanDefinition(); 8. 9. try { 10. //SpringBoot项目项目启动时AnnotatedBeanDefinition 上面注入的启动类的BeanDefinition 11. if (bd instanceof AnnotatedBeanDefinition) { 12. this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName()); 13. } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) { 14. this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName()); 15. } else { 16. this.parse(bd.getBeanClassName(), holder.getBeanName()); 17. } 18. } catch (BeanDefinitionStoreException var6) { 19. throw var6; 20. } catch (Throwable var7) { 21. throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7); 22. } 23. 24. // 加载默认的配置 就是加载.pom中的的依赖 25. this.deferredImportSelectorHandler.process(); 26. }
1. protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { 2. this.processConfigurationClass(new ConfigurationClass(metadata, beanName)); 3. } 4. 5. 6. 7. protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { 8. ... 9. 10. do { 11. //递归处理Bean,如果有父类,递归处理,直到顶层父类 12. sourceClass = this.doProcessConfigurationClass(configClass, sourceClass); 13. } 14. ... 15. } 16. } 17. 18. 19. 20. // ConfigurationClassParser类 21. protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) 22. throws IOException { 23. 24. // Recursively process any member (nested) classes first 25. //首先递归处理内部类,(SpringBoot项目的主类一般没有内部类) 26. processMemberClasses(configClass, sourceClass); 27. 28. // Process any @PropertySource annotations 29. // 针对 @PropertySource 注解的属性配置处理 30. for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( 31. sourceClass.getMetadata(), PropertySources.class, 32. org.springframework.context.annotation.PropertySource.class)) { 33. if (this.environment instanceof ConfigurableEnvironment) { 34. processPropertySource(propertySource); 35. } else { 36. logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + 37. "]. Reason: Environment must implement ConfigurableEnvironment"); 38. } 39. } 40. 41. // Process any @ComponentScan annotations 42. // 根据 @ComponentScan 注解,扫描项目中的Bean(SpringBoot 启动类上有该注解) 43. Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( 44. sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); 45. if (!componentScans.isEmpty() && 46. !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { 47. for (AnnotationAttributes componentScan : componentScans) { 48. // The config class is annotated with @ComponentScan -> perform the scan immediately 49. // 立即执行扫描,(SpringBoot项目为什么是从主类所在的包扫描,这就是关键了) 50. Set<BeanDefinitionHolder> scannedBeanDefinitions = 51. this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); 52. // Check the set of scanned definitions for any further config classes and parse recursively if needed 53. for (BeanDefinitionHolder holder : scannedBeanDefinitions) { 54. BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); 55. if (bdCand == null) { 56. bdCand = holder.getBeanDefinition(); 57. } 58. // 检查是否是ConfigurationClass(是否有configuration/component两个注解),如果是,递归查找该类相关联的配置类。 59. // 所谓相关的配置类,比如@Configuration中的@Bean定义的bean。或者在有@Component注解的类上继续存在@Import注解。 60. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { 61. parse(bdCand.getBeanClassName(), holder.getBeanName()); 62. } 63. } 64. } 65. } 66. 67. // Process any @Import annotations 68. //递归处理 @Import 注解(SpringBoot项目中经常用的各种@Enable*** 注解基本都是封装的@Import) 69. processImports(configClass, sourceClass, getImports(sourceClass), true); 70. 71. // Process any @ImportResource annotations 72. AnnotationAttributes importResource = 73. AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); 74. if (importResource != null) { 75. String[] resources = importResource.getStringArray("locations"); 76. Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); 77. for (String resource : resources) { 78. String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); 79. configClass.addImportedResource(resolvedResource, readerClass); 80. } 81. } 82. 83. // Process individual @Bean methods 84. Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); 85. for (MethodMetadata methodMetadata : beanMethods) { 86. configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); 87. } 88. 89. // Process default methods on interfaces 90. processInterfaces(configClass, sourceClass); 91. 92. // Process superclass, if any 93. if (sourceClass.getMetadata().hasSuperClass()) { 94. String superclass = sourceClass.getMetadata().getSuperClassName(); 95. if (superclass != null && !superclass.startsWith("java") && 96. !this.knownSuperclasses.containsKey(superclass)) { 97. this.knownSuperclasses.put(superclass, configClass); 98. // Superclass found, return its annotation metadata and recurse 99. return sourceClass.getSuperClass(); 100. } 101. } 102. 103. // No superclass -> processing is complete 104. return null; 105. } 106. 107. 108.
进入Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
1. public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { 2. ... 3. return scanner.doScan(StringUtils.toStringArray(basePackages)); 4. } 5. 6. 7. 8. protected Set<BeanDefinitionHolder> doScan(String... basePackages) { 9. 10. 11. for(int var5 = 0; var5 < var4; ++var5) { 12. String basePackage = var3[var5]; 13. //扫描注解 查到bean 转为BeanDefinition 14. Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage); 15. Iterator var8 = candidates.iterator(); 16. 17. while(var8.hasNext()) { 18. BeanDefinition candidate = (BeanDefinition)var8.next(); 19. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); 20. candidate.setScope(scopeMetadata.getScopeName()); 21. String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); 22. if (candidate instanceof AbstractBeanDefinition) { 23. this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName); 24. } 25. 26. if (candidate instanceof AnnotatedBeanDefinition) { 27. AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate); 28. } 29. 30. if (this.checkCandidate(beanName, candidate)) { 31. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); 32. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 33. beanDefinitions.add(definitionHolder); 34. //注入ioc 35. this.registerBeanDefinition(definitionHolder, this.registry); 36. } 37. } 38. } 39. 40. return beanDefinitions; 41. }
二.个人理解,获取bean的过程
- 获取要扫描的包的地址。
- 通过注解扫描出bean 。
- BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);将该BeanDefinition注册到IoC容器的beanDefinitionMap中 。
1. public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { 2. String beanName = definitionHolder.getBeanName(); 3. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 4. String[] aliases = definitionHolder.getAliases(); 5. if (aliases != null) { 6. String[] var4 = aliases; 7. int var5 = aliases.length; 8. 9. for(int var6 = 0; var6 < var5; ++var6) { 10. String alias = var4[var6]; 11. registry.registerAlias(beanName, alias); 12. } 13. } 14. 15. }
其中在 parse 中的 this.deferredImportSelectorHandler.process(); 加载pom文件中的依赖。
其中后置处理器可以修改BeanDefinition,可以参考以下实例
三.bean的生命周期
- 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为连Autowired注解都是没有解析的;
- 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;
- 如果Bean实现了BeanNameAware接口,则调用setBeanName方法;
- 如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;
- 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;
- 调用BeanPostProcessor的postProcessBeforeInitialization方法;
- 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;
- 如果Bean定义了init-method方法,则调用Bean的init-method方法;
- 调用BeanPostProcessor的postProcessAfterInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的上下文中,直到被销毁;
- 如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method声明了销毁方法也会被调用。