马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
设置IOC容器
- public ConfigurableApplicationContext run(String... args) {
- // -- snip
- try {
- // context的类型是AnnotationConfigServletWebServerApplicationContext
- context = createApplicationContext();
- context.setApplicationStartup(this.applicationStartup);
- // 1. 准备容器
- prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
- // 2. 刷新容器
- refreshContext(context);
- afterRefresh(context, applicationArguments);
- startup.started();
- if (this.logStartupInfo) {
- new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), startup);
- }
- listeners.started(context, startup.timeTakenToStarted());
- callRunners(context, applicationArguments);
- }
- catch (Throwable ex) {
- throw handleRunFailure(context, ex, listeners);
- }
- try {
- if (context.isRunning()) {
- listeners.ready(context, startup.ready());
- }
- }
- catch (Throwable ex) {
- throw handleRunFailure(context, ex, null);
- }
- return context;
- }
复制代码 1. 准备容器
- private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
- ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments, Banner printedBanner) {
- context.setEnvironment(environment);
- // 配置容器的类加载器、资源加载器、类型转换器
- postProcessApplicationContext(context);
- // 如果JVM允许AOT,则配置AOT相关的ApplicationContextInitializer
- // AOT(ahead of time)是在程序运行前将字节码编译成机器码,JIT(just in time)是程序边运行边将字节码编译成机器码。普通SpringBoot用的是JIT
- addAotGeneratedInitializerIfNecessary(this.initializers);
- // 1. 执行初始化器
- applyInitializers(context);
- listeners.contextPrepared(context);
- // 关闭引导上下文
- bootstrapContext.close(context);
- if (this.logStartupInfo) {
- logStartupInfo(context.getParent() == null);
- logStartupProfileInfo(context);
- }
- // Add boot specific singleton beans
- // beanFactory的类型是DefaultListableBeanFactory
- ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
- // 向bean工厂注册单例applicationArguments
- beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
- if (printedBanner != null) {
- beanFactory.registerSingleton("springBootBanner", printedBanner);
- }
- if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
- // 配置是否允许循环依赖
- autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
- if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
- listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
- }
- }
- if (this.lazyInitialization) {
- // 设置延迟加载
- context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
- }
- if (this.keepAlive) {
- // KeepAlive()对象额外启动一个非守护线程,避免`SpringBoot`因为非守护线程结束而关闭JVM
- context.addApplicationListener(new KeepAlive());
- }
- // PropertySourceOrderingBeanFactoryPostProcessor是对@PropertySource注解修饰的类进行排序
- context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
- if (!AotDetector.useGeneratedArtifacts()) {
- // Load the sources
- Set<Object> sources = getAllSources();
- Assert.notEmpty(sources, "Sources must not be empty");
- load(context, sources.toArray(new Object[0]));
- }
- listeners.contextLoaded(context);
- }
复制代码 1. 实行初始化器
- protected void applyInitializers(ConfigurableApplicationContext context) {
- for (ApplicationContextInitializer initializer : getInitializers()) {
- Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
- ApplicationContextInitializer.class);
- Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
- initializer.initialize(context);
- }
- }
复制代码 SpringBoot默认的初始化器有7个。从上到下它们的功能分别是
0. 实行情况属性context.initializer.classes指定的初始化器。它的优先级最高。
- 向容器添加一个CachingMetadataReaderFactoryPostProcessor。
- 初始化容器的ID。
- 向容器增长一个处理处罚错误告警的BeanFactoryPostProcessor。
- RSocket是基于Reactive Streams的通讯协议。
- 向容器设置server.port端口属性。
- 向容器中设置ConditionEvaluationReportListener。
2.革新容器

终极调用的是AbstractApplicationContext#refresh()方法。
- private final Lock startupShutdownLock = new ReentrantLock();
- public void refresh() throws BeansException, IllegalStateException {
- // startupShutdownLock锁是防止当前线程刷新容器,别的线程关闭容器。
- this.startupShutdownLock.lock();
- try {
- this.startupShutdownThread = Thread.currentThread();
- StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
- // Prepare this context for refreshing.
- // 1. 准备刷新
- prepareRefresh();
- // Tell the subclass to refresh the internal bean factory.
- // 2. 重获容器
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- // Prepare the bean factory for use in this context.
- // 3. 配置容器
- prepareBeanFactory(beanFactory);
- try {
- // Allows post-processing of the bean factory in context subclasses.
- // 4. 容器子类添加后处理器
- postProcessBeanFactory(beanFactory);
-
- // 标记阶段
- StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
- // Invoke factory processors registered as beans in the context.
-
- // 5. 调用BeanFactory后处理器
- invokeBeanFactoryPostProcessors(beanFactory);
- // Register bean processors that intercept bean creation.
- // 6. 注册bean后处理器
- registerBeanPostProcessors(beanFactory);
- beanPostProcess.end();
- // Initialize message source for this context.
- // 向bean工厂注册一个名为`messageSource`的单例bean
- initMessageSource();
- // Initialize event multicaster for this context.
- // 向bean工厂注册一个名为`applicationEventMulticaster`的SimpleApplicationEventMulticaster对象
- initApplicationEventMulticaster();
- // Initialize other special beans in specific context subclasses.
- // 7. tomcat初始化
- onRefresh();
- // Check for listener beans and register them.
- registerListeners();
- // Instantiate all remaining (non-lazy-init) singletons.
- finishBeanFactoryInitialization(beanFactory);
- // Last step: publish corresponding event.
- finishRefresh();
- }
- catch (RuntimeException | Error ex ) {
- if (logger.isWarnEnabled()) {
- logger.warn("Exception encountered during context initialization - " +
- "cancelling refresh attempt: " + ex);
- }
- // Destroy already created singletons to avoid dangling resources.
- destroyBeans();
- // Reset 'active' flag.
- cancelRefresh(ex);
- // Propagate exception to caller.
- throw ex;
- }
- finally {
- contextRefresh.end();
- }
- }
- finally {
- this.startupShutdownThread = null;
- this.startupShutdownLock.unlock();
- }
- }
复制代码 1. 准备革新
- protected void prepareRefresh() {
- // Switch to active.
- this.startupDate = System.currentTimeMillis(); // startupDate的类型是`long`,标记容器启动时刻
- this.closed.set(false); // close的类型是`AtomicBoolean`,标记当前容器是否已就绪
- this.active.set(true); // active的类型是`AtomicBoolean`,标记当前容器是否活跃
- // 源码此处有log
- // Initialize any placeholder property sources in the context environment.
- // 初始化名称为`servletContextInitParams`的ServletContextPropertySource`,即初始化Servlet相关属性
- initPropertySources();
- // Validate that all properties marked as required are resolvable:
- // see ConfigurablePropertyResolver#setRequiredProperties
- getEnvironment().validateRequiredProperties();
- // Store pre-refresh ApplicationListeners...
- // earlyApplicationListeners 刷新容器之前已存在的监听器
- if (this.earlyApplicationListeners == null) {
- this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
- }
- else {
- // Reset local application listeners to pre-refresh state.
- this.applicationListeners.clear();
- this.applicationListeners.addAll(this.earlyApplicationListeners);
- }
- // Allow for the collection of early ApplicationEvents,
- // to be published once the multicaster is available...
- this.earlyApplicationEvents = new LinkedHashSet<>();
- }
复制代码 2. 重获容器
- protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
- refreshBeanFactory();
- // 当前applicationContext是容器对象,但是包含了环境配置,事件发布器等等。而`getBeanFactory`返回的容器仅仅处理对象
- return getBeanFactory();
- }
复制代码- // GenericApplicationContext#refreshBeanFactory
- protected final void refreshBeanFactory() throws IllegalStateException {
- // refreshed的类型是`AtomicBoolean`,代表容器正在刷新,cas表示容器只能刷新一次
- if (!this.refreshed.compareAndSet(false, true)) {
- throw new IllegalStateException(
- "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
- }
- // 容器的id是`application`
- this.beanFactory.setSerializationId(getId());
- }
复制代码 3. 设置容器
- protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
- // Tell the internal bean factory to use the context's class loader etc.
- // 设置bean的类加载器,是`AppClassLoader`
- beanFactory.setBeanClassLoader(getClassLoader());
- // 设置SPEL解析器
- beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
- // 设置属性编辑器,将字符串属性转为java对象,比如将"false"字符串转为Boolean.False。
- beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
- // Configure the bean factory with context callbacks.
- // 配置bean后处理器。`ignoreDependencyInterface`表示容器不解析这些接口,不将接口的实现放入容器。
- //源码里是将这些接口放入`Set<Class<?>> ignoredDependencyInterfaces`。
- // 这些接口统一由`ApplicationContextAwareProcessor`处理。
- 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.ignoreDependencyInterface(ApplicationStartupAware.class);
- // BeanFactory interface not registered as resolvable type in a plain factory.
- // MessageSource registered (and found for autowiring) as a bean.
- // 指定BeanFactory.class接口的容器对象是beanfactory
- // 源码里就是将`BeanFactory.class`和`beanFactory`放入`Map<Class<?>, Object> resolvableDependencies`。
- 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.
- // 添加bean后处理器,ApplicationListenerDetector监听实现ApplicationListener接口的bean
- beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
- // Detect a LoadTimeWeaver and prepare for weaving, if found.
- // NativeDetector检测当前环境是否是GraalVM native镜像。
- if (!NativeDetector.inNativeImage() && 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.
- // 向容器注册名为"environment"的单例ApplicationServletEnvironment对象
- if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
- beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
- }
- // 向容器注册名为"systemProperties"的单例Properties对象
- if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
- beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
- }
- // 向容器注册名为"systemEnvironment"的`UnmodifiableMap`对象
- if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
- beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
- }
- // 向容器注册名为"applicationStartup"的单例DefaultApplicationStartup对象
- if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
- beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
- }
- }
复制代码 4. 容器子类添加后处理处罚器
ServletWebServerApplicationContext是容器实现类,它添加bean后处理处罚器。WebApplicationContextServletContextAwareProcessor是向容器添加servletContext。
- // org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
- protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
- beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
- beanFactory.ignoreDependencyInterface(ServletContextAware.class);
- registerWebApplicationScopes();
- }
复制代码 5. 调用BeanFactory后处理处罚器
终极调用的是PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法。后处理处罚器分2种,一种是BeanDefinitionRegistryPostProcessors,处理处罚BeanDefinitionRegistry中登记的BeanDefinition。BeanDefinition是bean的界说类,是对差别泉源(Annotation注解,xml文件)的容器界说(scope, beanName)的抽象。容器根据界说类创建容器。一种是BeanFactoryPostProcessors,处理处罚容器。
先看BeanDefinitionRegistryPostProcessors。起首处理处罚PriorityOrdered接口,之后处理处罚Ordered接口,别的的末了处理处罚。
invokeBeanDefinitionRegistryPostProcessors方法让每个后处理处罚器postProcessor调用本身的postProcessBeanDefinitionRegistry方法。此中有个org.springframework.context.annotation.ConfigurationClassPostProcessor将全部@Confuguration注解类剖析成BeanDefinitionHolder。
- private static void invokeBeanDefinitionRegistryPostProcessors(
- Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
- for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
- StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
- .tag("postProcessor", postProcessor::toString);
- postProcessor.postProcessBeanDefinitionRegistry(registry);
- postProcessBeanDefRegistry.end();
- }
- }
复制代码 BeanFactoryPostProcessors也是按照优先级举行处理处罚。
处理处罚竣过后,删除缓存。
- @Override
- public void clearMetadataCache() {
- super.clearMetadataCache();
- this.mergedBeanDefinitionHolders.clear();
- clearByTypeCache();
- }
复制代码
6. 注册bean后处理处罚器
registerBeanPostProcessors方法也是按照优先级注册bean后处理处罚方法。这里的注册指的是将BeanPostProcessors放入容器,即abstractBeanFactory.addBeanPostProcessors(postProcessors)。而不是实行BeanPostProcessors,由于此时还没有创建bean。
末了将后处理处罚器重新注册一遍。而且添加ApplicationListenerDetector容器后处理处罚器。
7. tomcat初始化
onfresh()是交给容器子类自界说初始化,web容器在此设置web情况而且启动tomcat。
|