解读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