上篇给大家介绍了Spring Boot启动过程完全解析(一),大家可以点击参考下
该说refreshContext(context)了,首先是判断context是否是AbstractApplicationContext派生类的实例,之后调用了强转为AbstractApplicationContext类型并调用它的refresh方法。由于AnnotationConfigEmbeddedWebApplicationContext继承自EmbeddedWebApplicationContext,所以会执行EmbeddedWebApplicationContext的refresh方法,继而执行其中的super.refresh。这个refresh也就是AbstractApplicationContext的refresh方法了,它内部是一个synchronized锁全局的代码块,同样的加锁方法还有这个类里的close和registerShutdownHook方法。
同步代码块中第一个方法prepareRefresh,首先会执行AnnotationConfigEmbeddedWebApplicationContext的prepareRefresh方法:
protected void prepareRefresh() { this.scanner.clearCache(); super.prepareRefresh(); }</div>
这个super也就是AbstractApplicationContext,它的prepareRefresh方法逻辑是:生成启动时间;设置closed状态为false;active状态为true;initPropertySources方法主要是调用了AbstractEnvironment的getPropertySources方法获取了之前SpringApplication的prepareEnvironment方法中getOrCreateEnvironment方法准备的各种环境变量及配置并用于初始化ServletPropertySources。具体的servletContextInitParams这些是在环境对象初始化时由各集成级别Environment的customizePropertySources方法中初始化的。
接着的getEnvironment().validateRequiredProperties()方法实际执行了AbstractEnvironment中的this.propertyResolver.validateRequiredProperties(),主要是验证了被占位的key如果是required的值不能为null。prepareRefresh的最后是初始化this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>()。*****
只够是获取BeanFactory实例的方法obtainFreshBeanFactory(),首先在refreshBeanFactory方法中用原子布尔类型判断是否刷新过,BeanFactory实例是在createApplicationContext创建Context实例时被创建的,如果没有刷新则设置一个用于序列化的id,id是ContextIdApplicationContextInitializer初始化设置的(如未配置该初始化器,是有一个默认ObjectUtils.identityToString(this)生成的),这个id的生成规则是spring.config.name截取的+":"+server.port的占位截取。设置序列化id时,同时保存了一个id和弱引用DefaultListableBeanFactory实例映射。
得到了beanFactory后就是prepareBeanFactory(beanFactory)了,逻辑是注册了BeanClassLoader用于注入的bean实例的创建;StandardBeanExpressionResolver用于EL表达式,比如配置文件或者@Value("#{...}")等使用;用ResourceEditorRegistrar注册属性转换器,比如xml配置的bean属性都是用的字符串配置的要转成真正的属性类型;addBeanPostProcessor(new ApplicationContextAwareProcessor(this))注册ApplicationContextAwareProcessor,它的invokeAwareInterfaces方法会对实现指定接口的bean调用指定的set方法;ignoreDependencyInterface忽略对这些接口的自动装配,比如Aware这些是要做独立处理的,不适合通用的方法;然后是有几个类型直接手动注册,比如BeanFactory,这个很好理解;接着注册一个后置处理器ApplicationListenerDetector的实例,addBeanPostProcessor注册的会按照注册先后顺序执行;这个方法的最后判断了特定的4个bean名字,如果存在会做相应注册,包括loadTimeWeaver、environment、systemProperties和systemEnvironment。补充一点,在最开始创建实例的时候还执行过ignoreDependencyInterface(BeanNameAware.class);ignoreDependencyInterface(BeanFactoryAware.class);ignoreDependencyInterface(BeanClassLoaderAware.class)。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // Register default environment beans. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }</div>
之后到了refresh的postProcessBeanFactory方法,首先是会走到AnnotationConfigEmbeddedWebApplicationContext的Override,需要注意的一点是,这是web环境,如果不是是不会加载这个上下文的,也就不会这么走。它重写的第一步是先走super也就是EmbeddedWebApplicationContext的postProcessBeanFactory,这里又注册了个后置处理器WebApplicationContextServletContextAwareProcessor的实例,构造参数是this,也就是当前上下文,同时忽略ServletContextAware接口,这个接口是用于获取ServletContext的,为什么要忽略呢,我猜应该是因为我们既然有了web应用并且内嵌servlet的上下文实例,还要ServletContext的实现就没什么用了,还有可能出现冲突的问题,有空我再确认下。然后是配置的basePackages和annotatedClasses:
@Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { super.postProcessBeanFactory(beanFactory); if (this.basePackages != null && this.basePackages.length > 0) { this.scanner.scan(this.basePackages); } if (this.annotatedClasses != null && this.annotatedClasses.length > 0) { this.reader.register(this.annotatedClasses); } }</div>
到了invokeBeanFactoryPostProcessors方法,这个方法就是执行之前注册的BeanFactory后置处理器的地方。代码一目了然,PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors中只是有些排序的逻辑,我就不说了:
/** * Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given. * <p>Must be called before singleton instantiation. */ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (