怎樣分析springboot,springboot2源碼2-SpringApplication運行

 2023-10-18 阅读 30 评论 0

摘要:SpringApplication的run方法 public ConfigurableApplicationContext run(String... args) {//時間監控StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exc

SpringApplication的run方法

public ConfigurableApplicationContext run(String... args) {//時間監控StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();//java.awt.headless是J2SE的一種模式用于在缺少顯示屏、鍵盤或者鼠標時的系統配置,很多監控工具如jconsole 需要將該值設置為true,系統變量默認為trueconfigureHeadlessProperty();//獲取spring.factories中的監聽器變量,args為指定的參數數組,默認為當前類SpringApplication//第一步:獲取并啟動監聽器SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//第二步:構造容器環境ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);//設置需要忽略的beanconfigureIgnoreBeanInfo(environment);//第三步:打印banner和創建容器Banner printedBanner = printBanner(environment);context = createApplicationContext();//第四步:實例化SpringBootExceptionReporter.class,用來支持報告關于啟動的錯誤exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//第五步:準備容器prepareContext(context, environment, listeners, applicationArguments,printedBanner);//第六步:刷新容器refreshContext(context);//第七步:刷新容器后的擴展接口afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}//第八步:監聽器已啟動listeners.started(context);//第九步:執行ApplicationRunner和CommandLineRunnercallRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;}

第一步:獲取并啟動監聽器

1.獲取運行監聽器
SpringApplication

		SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();
	private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

EventPublishingRunListener實例化,添加10個監聽器

	public EventPublishingRunListener(SpringApplication application, String[] args) {this.application = application;this.args = args;this.initialMulticaster = new SimpleApplicationEventMulticaster();for (ApplicationListener<?> listener : application.getListeners()) {this.initialMulticaster.addApplicationListener(listener);}}

怎樣分析springboot、AbstractApplicationEventMulticaster先去掉監聽器的代理對象,然后添加監聽器對象

	@Overridepublic void addApplicationListener(ApplicationListener<?> listener) {synchronized (this.retrievalMutex) {// Explicitly remove target for a proxy, if registered already,// in order to avoid double invocations of the same listener.Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);if (singletonTarget instanceof ApplicationListener) {this.defaultRetriever.applicationListeners.remove(singletonTarget);}this.defaultRetriever.applicationListeners.add(listener);this.retrieverCache.clear();}}

SpringApplicationRunListeners 存儲運行監聽器

	private final List<SpringApplicationRunListener> listeners;SpringApplicationRunListeners(Log log,Collection<? extends SpringApplicationRunListener> listeners) {this.log = log;this.listeners = new ArrayList<>(listeners);}

2.運行監聽器啟動starting
SpringApplicationRunListeners

	public void starting() {for (SpringApplicationRunListener listener : this.listeners) {listener.starting();}}

EventPublishingRunListener

	private final SimpleApplicationEventMulticaster initialMulticaster;@Overridepublic void starting() {this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));}

Springboot項目、SimpleApplicationEventMulticaster

	@Overridepublic void multicastEvent(ApplicationEvent event) {multicastEvent(event, resolveDefaultEventType(event));}@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {Executor executor = getTaskExecutor();if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}

AbstractApplicationEventMulticaster

	final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {Object source = event.getSource();Class<?> sourceType = (source != null ? source.getClass() : null);ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);// Quick check for existing entry on ConcurrentHashMap...ListenerRetriever retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}if (this.beanClassLoader == null ||(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {// Fully synchronized building and caching of a ListenerRetrieversynchronized (this.retrievalMutex) {retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}retriever = new ListenerRetriever(true);Collection<ApplicationListener<?>> listeners =retrieveApplicationListeners(eventType, sourceType, retriever);this.retrieverCache.put(cacheKey, retriever);return listeners;}}else {// No ListenerRetriever caching -> no synchronization necessaryreturn retrieveApplicationListeners(eventType, sourceType, null);}}

SimpleApplicationEventMulticaster

	protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

LoggingApplicationListener打印日志

	@Overridepublic void onApplicationEvent(ApplicationEvent event) {//在springboot啟動的時候if (event instanceof ApplicationStartedEvent) {onApplicationStartedEvent((ApplicationStartedEvent) event);}//springboot的Environment環境準備完成的時候else if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}//在springboot容器的環境設置完成以后else if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent((ApplicationPreparedEvent) event);}//容器關閉的時候else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {onContextClosedEvent();}//容器啟動失敗的時候else if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent();}}private void onApplicationStartingEvent(ApplicationStartingEvent event) {this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());this.loggingSystem.beforeInitialize();}

springbootcms項目,因為我們的事件類型為ApplicationStartedEvent,所以會執行onApplicationStartedEvent((ApplicationStartedEvent) event);。springBoot會在運行過程中的不同階段,發送各種事件,來執行對應監聽器的對應方法。

二:環境構建

SpringApplication

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environment//獲取對應的ConfigurableEnvironmentConfigurableEnvironment environment = getOrCreateEnvironment();//配置configureEnvironment(environment, applicationArguments.getSourceArgs());//發布環境已準備事件,這是第二次發布事件listeners.environmentPrepared(environment);bindToSpringApplication(environment);if (this.webApplicationType == WebApplicationType.NONE) {environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}ConfigurationPropertySources.attach(environment);return environment;}//返回StandardServletEnvironmentprivate ConfigurableEnvironment getOrCreateEnvironment() {if (this.environment != null) {return this.environment;}switch (this.webApplicationType) {case SERVLET:return new StandardServletEnvironment();case REACTIVE:return new StandardReactiveWebEnvironment();default:return new StandardEnvironment();}}

SpringApplicationRunListeners

public void environmentPrepared(ConfigurableEnvironment environment) {for (SpringApplicationRunListener listener : this.listeners) {listener.environmentPrepared(environment);}}

EventPublishingRunListener從10個監聽器中,選出ApplicationEnvironmentPreparedEvent類型的,調用監聽器

	private final SimpleApplicationEventMulticaster initialMulticaster;@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));}

spring boot注解詳解。SimpleApplicationEventMulticaster

	@Overridepublic void multicastEvent(ApplicationEvent event) {multicastEvent(event, resolveDefaultEventType(event));}@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {Executor executor = getTaskExecutor();if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

比如有ConfigFileApplicationListener,加載配置文件EnvironmentPostProcessor的3個后處理器

@Overridepublic void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent(event);}}private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();postProcessors.add(this);AnnotationAwareOrderComparator.sort(postProcessors);for (EnvironmentPostProcessor postProcessor : postProcessors) {postProcessor.postProcessEnvironment(event.getEnvironment(),event.getSpringApplication());}}List<EnvironmentPostProcessor> loadPostProcessors() {return SpringFactoriesLoader.loadFactories(EnvironmentPostProcessor.class,getClass().getClassLoader());}
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor

第三步:打印banner和創建容器

SpringApplication

			Banner printedBanner = printBanner(environment);context = createApplicationContext();
	public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";//返回AnnotationConfigServletWebServerApplicationContextprotected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {switch (this.webApplicationType) {case SERVLET:contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);break;case REACTIVE:contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);break;default:contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);}}catch (ClassNotFoundException ex) {throw new IllegalStateException("Unable create a default ApplicationContext, "+ "please specify an ApplicationContextClass",ex);}}return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);}

AnnotationConfigServletWebServerApplicationContext

	public AnnotationConfigServletWebServerApplicationContext() {this.reader = new AnnotatedBeanDefinitionReader(this);this.scanner = new ClassPathBeanDefinitionScanner(this);}

springboot項目源碼?AnnotatedBeanDefinitionReader

	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry;this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}

AnnotationConfigUtils

	public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);}public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME ="org.springframework.context.annotation.internalConfigurationAnnotationProcessor";public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}//注冊了6個內部bean,默認容量是8,加載因子是0.75,正好是6個Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

注冊了內部bean,名稱比較奇怪,不是類的簡單名稱的首字母小寫,而是全限定名前面加上internal
在這里插入圖片描述
ConfigurationClassPostProcessor比較重要,后面的自動配置用到了

第四步:報告錯誤信息

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
在這里插入代碼片

該類主要是在項目啟動失敗之后,打印log:

	private void reportFailure(Collection<SpringBootExceptionReporter> exceptionReporters,Throwable failure) {try {for (SpringBootExceptionReporter reporter : exceptionReporters) {if (reporter.reportException(failure)) {//上報錯誤logregisterLoggedException(failure);return;}}}catch (Throwable ex) {// Continue with normal handling of the original failure}if (logger.isErrorEnabled()) {logger.error("Application run failed", failure);registerLoggedException(failure);}}

第五步:準備容器

spring源碼、這一步主要是在容器刷新之前的準備動作。包含一個非常關鍵的操作:將啟動類注入容器,為后續開啟自動化配置奠定基礎。
SpringApplication

private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {//設置容器環境,包括各種變量context.setEnvironment(environment);//執行容器后置處理postProcessApplicationContext(context);//執行容器中的ApplicationContextInitializer(包括 spring.factories和自定義的實例)applyInitializers(context);//發送容器已經準備好的事件,通知各監聽器listeners.contextPrepared(context);//打印logif (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beans//注冊啟動參數bean,這里將容器指定的參數封裝成bean,注入容器context.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments);//設置bannerif (printedBanner != null) {context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);}// 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);}

容器的后置處理,這里默認不執行任何邏輯,因為beanNameGenerator和resourceLoader默認為空。之所以這樣做,是springBoot留給我們的擴展處理方式

	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());}}}

applyInitializers加載4個初始化器的共3個內部后處理器

	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);}}
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

比如ConfigurationWarningsApplicationContextInitializer

	protected static final class ConfigurationWarningsPostProcessorimplements PriorityOrdered, BeanDefinitionRegistryPostProcessor {...}@Overridepublic void initialize(ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));}

Springboot教程,加載啟動指定類(重點)
這里會將我們的啟動類加載spring容器beanDefinitionMap中,為后續springBoot 自動化配置奠定基礎,springBoot為我們提供的各種注解配置也與此有關。

	protected void load(ApplicationContext context, Object[] sources) {if (logger.isDebugEnabled()) {logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));}BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);if (this.beanNameGenerator != null) {loader.setBeanNameGenerator(this.beanNameGenerator);}if (this.resourceLoader != null) {loader.setResourceLoader(this.resourceLoader);}if (this.environment != null) {loader.setEnvironment(this.environment);}loader.load();}

需要注意的是,springBoot2會優先選擇groovy加載方式,找不到再選用java方式。或許groovy動態加載class文件的性能更勝一籌。
但是還是默認選擇java加載
BeanDefinitionLoader

	public int load() {int count = 0;for (Object source : this.sources) {count += load(source);}return count;}選擇類加載private int load(Object source) {Assert.notNull(source, "Source must not be null");if (source instanceof Class<?>) {return load((Class<?>) source);}if (source instanceof Resource) {return load((Resource) source);}if (source instanceof Package) {return load((Package) source);}if (source instanceof CharSequence) {return load((CharSequence) source);}throw new IllegalArgumentException("Invalid source type " + source.getClass());}private final AnnotatedBeanDefinitionReader annotatedReader;private int load(Class<?> source) {if (isGroovyPresent()&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,GroovyBeanDefinitionSource.class);load(loader);}if (isComponent(source)) {//以注解的方式,將啟動類bean信息存入beanDefinitionMapthis.annotatedReader.register(source);return 1;}return 0;}啟動類SpringBootApplication注解,里面繼承Configuration注解,繼承Component注解,返回trueprivate boolean isComponent(Class<?> type) {// This has to be a bit of a guess. The only way to be sure that this type is// eligible is to make a bean definition out of it and try to instantiate it.if (AnnotationUtils.findAnnotation(type, Component.class) != null) {return true;}// Nested anonymous classes are not eligible for registration, nor are groovy// closuresif (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass()|| type.getConstructors() == null || type.getConstructors().length == 0) {return false;}return true;}

AnnotatedBeanDefinitionReader

	public void register(Class<?>... annotatedClasses) {for (Class<?> annotatedClass : annotatedClasses) {registerBean(annotatedClass);}}public void registerBean(Class<?> annotatedClass) {doRegisterBean(annotatedClass, null, null, null);}<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);}

我們的啟動類就被包裝成AnnotatedGenericBeanDefinition了,后續啟動類的處理都基于該對象了。

Spring boot。通知監聽器,容器已準備就緒

listeners.contextLoaded(context);

主還是針對一些日志等監聽器的響應處理。

第六步:刷新容器

refresh方法在spring整個源碼體系中舉足輕重,是實現 ioc 和 aop的關鍵
SpringApplication

	protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);((AbstractApplicationContext) applicationContext).refresh();}

AbstractApplicationContext

synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing./*** 刷新上下文環境* 初始化上下文環境,對系統的環境變量或者系統屬性進行準備和校驗* 如環境變量中必須設置某個值才能運行,否則不能運行,這個時候可以在這里加這個校驗,* 重寫initPropertySources方法就好了*/prepareRefresh();// Tell the subclass to refresh the internal bean factory./*** 初始化BeanFactory,解析XML,相當于之前的XmlBeanFactory的操作,*/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context./*** 為上下文準備BeanFactory,即對BeanFactory的各種功能進行填充,如常用的注解@Autowired @Qualifier等* 設置SPEL表達式#{key}的解析器* 設置資源編輯注冊器,如PerpertyEditorSupper的支持* 添加ApplicationContextAwareProcessor處理器* 在依賴注入忽略實現*Aware的接口,如EnvironmentAware、ApplicationEventPublisherAware等* 注冊依賴,如一個bean的屬性中含有ApplicationEventPublisher(beanFactory),則會將beanFactory的實例注入進去*/prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses./*** 提供子類覆蓋的額外處理,即子類處理自定義的BeanFactoryPostProcess*/postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context./*** 激活各種BeanFactory處理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor* 執行對應的postProcessBeanDefinitionRegistry方法 和  postProcessBeanFactory方法*/invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation./*** 注冊攔截Bean創建的Bean處理器,即注冊BeanPostProcessor,不是BeanFactoryPostProcessor,注意兩者的區別* 注意,這里僅僅是注冊,并不會執行對應的方法,將在bean的實例化時執行對應的方法*/registerBeanPostProcessors(beanFactory);// Initialize message source for this context./*** 初始化上下文中的資源文件,如國際化文件的處理等*/initMessageSource();// Initialize event multicaster for this context./*** 初始化上下文事件廣播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher*/initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses./*** 給子類擴展初始化其他Bean*/onRefresh();// Check for listener beans and register them./*** 在所有bean中查找listener bean,然后注冊到廣播器中*/registerListeners();// Instantiate all remaining (non-lazy-init) singletons./*** 設置轉換器* 注冊一個默認的屬性值解析器* 凍結所有的bean定義,說明注冊的bean定義將不能被修改或進一步的處理* 初始化剩余的非惰性的bean,即初始化非延遲加載的bean*/finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event./*** 初始化生命周期處理器DefaultLifecycleProcessor,DefaultLifecycleProcessor含有start方法和stop方法,spring啟動的時候調用start方法開始生命周期,* spring關閉的時候調用stop方法來結束生命周期,通常用來配置后臺程序,啟動有一直運行,如一直輪詢kafka* 啟動所有實現了Lifecycle接口的類* 通過spring的事件發布機制發布ContextRefreshedEvent事件,以保證對應的監聽器做進一步的處理,即對那種在spring啟動后需要處理的一些類,這些類實現了* ApplicationListener<ContextRefreshedEvent> ,這里就是要觸發這些類的執行(執行onApplicationEvent方法)另外,spring的內置Event有ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、RequestHandleEvent* 完成初始化,通知生命周期處理器lifeCycleProcessor刷新過程,同時發出ContextRefreshEvent通知其他人*/finishRefresh();}catch (BeansException 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 {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}

第七步:刷新容器后的擴展接口

protected void afterRefresh(ConfigurableApplicationContext context,ApplicationArguments args) {}

擴展接口,設計模式中的模板方法,默認為空實現。如果有自定義需求,可以重寫該方法。比如打印一些啟動結束log,或者一些其它后置處理。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/148909.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息