本文主要是介绍Spring Boot2 源码 run prepareContext方法 (四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
10、准备应用上下文
private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {//设置环境参数context.setEnvironment(environment);postProcessApplicationContext(context);//所有ApplicationContextInitializer类 初始化applyInitializers(context);//contextPrepared监听事件listeners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// 获取beanFactory 为下面注册单例bean做准备ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// Load the sourcesSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[0]));//contextLoaded监听事件listeners.contextLoaded(context);}
public void setEnvironment(ConfigurableEnvironment environment) {// 设置context的environmentsuper.setEnvironment(environment); // 实例化context的reader属性的environment属性 this.reader.setEnvironment(environment); // 设置context的scanner属性的environment属性 this.scanner.setEnvironment(environment);
}
this.beanNameGenerator和this.resourceLoader为空应该是扩展用的
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {if (this.beanNameGenerator != null) {context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,this.beanNameGenerator);}if (this.resourceLoader != null) {if (context instanceof GenericApplicationContext) {((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);}if (context instanceof DefaultResourceLoader) {((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());}}}
初始化ApplicationContextInitializer,执行所有ApplicationContextInitializer类的initialize方法,赋值在SpringApplication的构造方法中
org.springframework.boot.context.config.DelegatingApplicationContextInitializer@f440ae7, org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer@5351a81e, org.springframework.boot.context.ContextIdApplicationContextInitializer@38bd9799, org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer@2884f688, org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer@7b8c24d, org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener@59f79bfc, org.springframework.boot.devtools.restart.RestartScopeInitializer@d22de04
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);}}
context.getBeanFactory();获取beanFactory ,赋值在GenericApplicationContext类中,此类是AnnotationConfigServletWebServerApplicationContext父类
public GenericApplicationContext() {this.beanFactory = new DefaultListableBeanFactory();}
重点关注一下load方法,加载启动类到spring容器
一直跟进load方法会找到AnnotatedBeanDefinitionReader类的doRegisterBean方法负责注册启动类,注册通俗上来讲将启动类存入DefaultListableBeanFactory类的this.beanDefinitionMap(ConcurrentHashMap)变量中。
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}abd.setInstanceSupplier(instanceSupplier);ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);abd.setScope(scopeMetadata.getScopeName());String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);if (qualifiers != null) {for (Class<? extends Annotation> qualifier : qualifiers) {if (Primary.class == qualifier) {abd.setPrimary(true);}else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);}BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}
这篇关于Spring Boot2 源码 run prepareContext方法 (四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!