解读Spring的入口(针对SpringBoot)

SpringApplication.run(args) 

0.在SpringApplication的构造函数中可以看到会调用初始化方法:

initialize(sources);

该方法会决定当前环境是否是web环境,并且从classpath下的/META-INF/spring.factories文件读取ApplicationInitializer和ApplicationListener的实现类,在后续的环境首先加载该Initializer类(prepareEnvironment方法中调用的applyInitializers(context)方法内),ApplicationListener的实现类是在prepareEnvironment方法中调用的listeners.contextPrepared(context)方法内。

发现在ApplicationContextInitializer接口的实现类中又添加了几个PostProcessor,包括:

ConfigurationWarningsPostProcessor
CachingMetadataReaderFactoryPostProcessor

1.准备环境

prepareEnvironment(listeners, applicationArguments)

上面的方法分别调用:

1).ConfigurableEnvironment getOrCreateEnvironment() // 初始化环境变量(如果是web环境,那么通过StandardServletEnvironment无参构造函数初始化,其实真正调用的是其父类的构造函数AbstractEnvironment,可以看到该构造函数中调用了模板方法:customizePropertySources(MutablePropertySources propertySources)),进一步从一下地方加载环境变量

1.1).servletConfigInitParams  —>initPropertySources(ServletContext servletContext, ServletConfig servletConfig) 在web容器启动的时候回过头来初始化
1.2).servletContextInitParams  —>initPropertySources(ServletContext servletContext, ServletConfig servletConfig) 在web容器启动的时候回过头来初始化
1.3).jndiProperties
1.4).systemProperties  —> System.getProperties()
1.5).systemEnvironment —> System.getenv()

进入方法配置环境

configureEnvironment(ConfigurableEnvironment environment,String[] args)

方法中调用了两个模板方法,分别加载PropertySource和Profiles

configurePropertySources(ConfigurableEnvironment environment, String[] args)

处理Map<String, Object> defaultProperties,可以在SpringBoot启动类的main方法中通过setDefaultProperties(Properties defaultProperties)方法设置(可以作为一个扩展点)

configureProfiles(ConfigurableEnvironment environment, String[] args)

设置environment的profiles属性

2).context = createApplicationContext(); 初始化spring容器

根据环境(是否有Servlet和ConfigurableWebApplicationContext)决定加载org.springframework.context.annotation.AnnotationConfigApplicationContext 还是
org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext

在AnnotationConfigEmbeddedWebApplicationContext的构造函数中初始化reader和scanner

this.reader = new AnnotatedBeanDefinitionReader(this);

this.scanner = new ClassPathBeanDefinitionScanner(this);

在AnnotatedBeanDefinitionReader的构造方法中我们需要关注的是方法:

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

该方法又注册了Spring的注解前置处理器

AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)

该方法中分别注册了一下7个内置注解前置处理器,以及其类型如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor->  ConfigurationClassPostProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor->   AutowiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor->   RequiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor->   CommonAnnotationBeanPostProcessor
org.springframework.context.annotation.internalPersistenceAnnotationProcessor->   PersistenceAnnotationBeanPostProcessor
org.springframework.context.event.internalEventListenerProcessor->   EventListenerMethodProcessor
org.springframework.context.event.internalEventListenerFactory->    DefaultEventListenerFactory

其中比较重要的是ConfigurationClassPostProcessor,用来处理配置类(@Configuration注解的类)和AutowiredAnnotationBeanPostProcessor,用来处理@Autowired和@Value注解

3.准备容器 prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner)

3.1). applyInitializers(context);
listeners.contextPrepared(context);

3.2). load(context, sources.toArray(new Object[sources.size()]));  // 注册SpringBoot类 

3.3).  refreshContext(context);

到了这一步基本可以跟下面的流程对接起来了

AbstractApplicationContext.refresh()

所有对注解解析类

ConfigurationClassParser.processConfigBeanDefinitions(BeanDefinitionRegistry registry)

真正的解析在该类的protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException方法

该方法会处理一下注解或者其他特征类

// Recursively process any member (nested) classes first
// Process any @PropertySource annotations
// Process any @ComponentScan annotations
// Process any @Import annotations
// Process any @ImportResource annotations
// Process individual @Bean methods
// Process default methods on interfaces
// Process superclass, if any

自动配置类的加载类(在上面注解解析类的解析过程中调用:处理@Import注解的过程中):

SpringFactoriesLoader.loadFactoryNames(Class<?> clazz, ClassLoader);

其中clazz指向EnableAutoConfiguration

转载自:https://blog.csdn.net/duanmuxiao/article/details/78131156

You may also like...