本章節(jié)繼續(xù)分析run方法的第15行代碼:
public ConfigurableApplicationContext run(String... args) {
1.StopWatch stopWatch = new StopWatch();
2.stopWatch.start();
3.ConfigurableApplicationContext context = null;
4.Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
5.configureHeadlessProperty();
6.SpringApplicationRunListeners listeners = getRunListeners(args);
7.listeners.starting();
try {
8. ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
9. ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
10. configureIgnoreBeanInfo(environment);
11. Banner printedBanner = printBanner(environment);
12. context = createApplicationContext();
13. exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
14. prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
15. refreshContext(context);
16. afterRefresh(context, applicationArguments);
17. stopWatch.stop();
18. if (this.logStartupInfo) {
19. new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
20. listeners.started(context);
21. callRunners(context, applicationArguments);
}
catch (Throwable ex) {
22. handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
23. listeners.running(context);
}
catch (Throwable ex) {
24. handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
- 其中第15行的代碼如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
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 (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();
}
}
}
本章節(jié)主要分析:registerBeanPostProcessors癞蚕,initMessageSource,initApplicationEventMulticaster,onRefresh,registerListeners,finishBeanFactoryInitialization拖陆,finishRefresh,destroyBeans,cancelRefresh,resetCommonCaches
registerBeanPostProcessors
- 具體代碼如下:registerBeanPostProcessors 本行代碼就是注冊(cè)BeanPostProcessors
具體代碼如下:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
先加個(gè)BeanPostProcessorChecker懊亡,會(huì)在beanPostBean創(chuàng)建bean的時(shí)候 打印信息或者打印不合格的bean
- 所以通過以上可知道 beanDeifion在BeanFactoryPostProcessor確定
- beanPostProcessor確定最終的bean(因?yàn)閎ean在初始化結(jié)束前后可以獲取修改bean)
- 查找 四種類型的beanPostProcessor 1.PriorityOrdered 2 Ordered 3 rest 4 internalPostProcessors
其中internalPostProcessors 屬于PriorityOrdered 和Ordered 同時(shí)是MergedBeanDefinitionPostProcessor 主要是修改RootBeanDefinition - RootBeanDefinition 它可能來源于多個(gè)原始Bean定義(繼承自其他的bean定義依啰,通常被注冊(cè)為GenericBeanDefinitions)。RootBeanDefinition從本質(zhì)上將是運(yùn)行時(shí)統(tǒng)一的Bean定義視圖店枣。
在配置階段速警,RootBeanDefinition也可能用于注冊(cè)獨(dú)立的bean定義。然而艰争,自從Spring2.5依賴坏瞄,編程地注冊(cè)bean定義建議使用 GenericBeanDefinition類。GenericBeanDefinition在允許動(dòng)態(tài)定義父依賴而不是硬編碼作為RootBeanDefinition方面有優(yōu)勢(shì)甩卓。 - 然后依次注冊(cè) PriorityOrdered Ordered 注冊(cè)其他的
- 最終在添加一個(gè)ApplicationListenerDetector鸠匀,其主要是檢測(cè)哪些bean是ApplicationListener
initMessageSource
這個(gè)是處理國(guó)際化的,具體代碼如下:
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}
- 首先檢測(cè)是否存在messageSource的bean逾柿,若是存在獲取這個(gè)bean 然后 若是存在父容器缀棍,就設(shè)置該父容器的messageSource為當(dāng)前容器的父messageSource,如果父容器不存在messageSource机错,就設(shè)置父容器本身爬范。設(shè)置父messageSource的意義是當(dāng)messageSource無法解析就交給父messageSource
- 若是不存在 設(shè)一個(gè)emtpymessageSource(DelegatingMessageSource ),繼續(xù)按照上述邏輯設(shè)置父MessageSource ,然后注冊(cè)該bean
initApplicationEventMulticaster 初始化容器的組播組件
- beanFactory.containsLocalBean(beanName) 只會(huì)在當(dāng)前容器中查找對(duì)應(yīng)的beanName是否存在
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
- 上述方法主要是查看當(dāng)前beanName是否存在對(duì)應(yīng)的ApplicationEventMulticaster 弱匪,存在就注冊(cè)該bean 不存在就設(shè)置SimpleApplicationEventMulticaster為組播組件
onRefresh的代碼如下:
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
public static ThemeSource initThemeSource(ApplicationContext context) {
if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
// Make ThemeSource aware of parent ThemeSource.
if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
if (hts.getParentThemeSource() == null) {
// Only set parent context as parent ThemeSource if no parent ThemeSource
// registered already.
hts.setParentThemeSource((ThemeSource) context.getParent());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using ThemeSource [" + themeSource + "]");
}
return themeSource;
}
else {
// Use default ThemeSource to be able to accept getTheme calls, either
// delegating to parent context's default or to local ResourceBundleThemeSource.
HierarchicalThemeSource themeSource = null;
if (context.getParent() instanceof ThemeSource) {
themeSource = new DelegatingThemeSource();
themeSource.setParentThemeSource((ThemeSource) context.getParent());
}
else {
themeSource = new ResourceBundleThemeSource();
}
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
"': using default [" + themeSource + "]");
}
return themeSource;
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
protected void initPropertySources() {
ConfigurableEnvironment env = getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
}
}
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
String[] beanNames = getBeanFactory()
.getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
throw new ApplicationContextException(
"Unable to start ServletWebServerApplicationContext due to missing "
+ "ServletWebServerFactory bean.");
}
if (beanNames.length > 1) {
throw new ApplicationContextException(
"Unable to start ServletWebServerApplicationContext due to multiple "
+ "ServletWebServerFactory beans : "
+ StringUtils.arrayToCommaDelimitedString(beanNames));
}
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
public WebServer getWebServer(ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null ? this.baseDirectory
: createTempDir("tomcat"));
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
File documentRoot = getValidDocumentRoot();
TomcatEmbeddedContext context = new TomcatEmbeddedContext();
if (documentRoot != null) {
context.setResources(new LoaderHidingResourceRoot(context));
}
context.setName(getContextPath());
context.setDisplayName(getDisplayName());
context.setPath(getContextPath());
File docBase = (documentRoot != null ? documentRoot
: createTempDir("tomcat-docbase"));
context.setDocBase(docBase.getAbsolutePath());
context.addLifecycleListener(new FixContextListener());
context.setParentClassLoader(
this.resourceLoader != null ? this.resourceLoader.getClassLoader()
: ClassUtils.getDefaultClassLoader());
resetDefaultLocaleMapping(context);
addLocaleMappings(context);
context.setUseRelativeRedirects(false);
configureTldSkipPatterns(context);
WebappLoader loader = new WebappLoader(context.getParentClassLoader());
loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
loader.setDelegate(true);
context.setLoader(loader);
if (isRegisterDefaultServlet()) {
addDefaultServlet(context);
}
if (shouldRegisterJspServlet()) {
addJspServlet(context);
addJasperInitializer(context);
}
context.addLifecycleListener(new StaticResourceConfigurer(context));
ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
host.addChild(context);
configureContext(context, initializersToUse);
postProcessContext(context);
}
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
initialize();
}
private void initialize() throws WebServerException {
TomcatWebServer.logger
.info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
try {
addInstanceIdToEngineName();
Context context = findContext();
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource())
&& Lifecycle.START_EVENT.equals(event.getType())) {
// Remove service connectors so that protocol binding doesn't
// happen when the service is started.
removeServiceConnectors();
}
});
// Start the server to trigger initialization listeners
this.tomcat.start();
// We can re-throw failure exception directly in the main thread
rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(),
getClass().getClassLoader());
}
catch (NamingException ex) {
// Naming is not enabled. Continue
}
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// blocking non-daemon to stop immediate shutdown
startDaemonAwaitThread();
}
catch (Exception ex) {
stopSilently();
throw new WebServerException("Unable to start embedded Tomcat", ex);
}
}
}
- 上述代碼主要是初始化ThemeSource青瀑,如果沒有就設(shè)置ResourceBundleThemeSource,整個(gè)邏輯類似于messageSource
- 創(chuàng)建WebServer
- 如果webServer和servletcontext都為null 則去獲取ServletWebServerFactory的bean
- ServletContextInitializer 存在的作用主要是讓ServletContextInitializer 可以被spring容器管理 而不被servlet容器管理,且與WebApplicationInitializer不同的是 實(shí)現(xiàn)ServletContextInitializer 的實(shí)現(xiàn)類且未實(shí)現(xiàn)WebApplicationInitializer 不會(huì)被SpringServletContainerInitializer檢測(cè)到斥难,因此不會(huì)有servlet容器自動(dòng)引導(dǎo)枝嘶。其onStartup方法 主要是配置ServletContext,比如any servlets, filters, listeners context-params and attributes
- WebApplicationInitializer 可以看做是Web.xml的替代哑诊,它是一個(gè)接口群扶。通過實(shí)現(xiàn)WebApplicationInitializer,在其中可以添加servlet镀裤,listener等竞阐,在加載Web項(xiàng)目的時(shí)候會(huì)加載這個(gè)接口實(shí)現(xiàn)類,從而起到web.xml相同的作用
SpringServletContainerInitializer作為ServletContainerInitializer的實(shí)現(xiàn)類暑劝,通過SPI機(jī)制骆莹,在web容器加載的時(shí)候會(huì)自動(dòng)的被調(diào)用。(這個(gè)類上還有一個(gè)注解@HandlesTypes担猛,它的作用是將感興趣的一些類注入到ServletContainerInitializerde)汪疮, 而這個(gè)類的方法又會(huì)掃描找到WebApplicationInitializer的實(shí)現(xiàn)類,調(diào)用它的onStartup方法毁习,從而起到啟動(dòng)web.xml相同的作用。
- getWebServer 主要是設(shè)置設(shè)置和啟動(dòng)內(nèi)置tomcat 設(shè)置Connector (默認(rèn)Nio協(xié)議)customizeConnector調(diào)整Connector
- prepareContext 就是設(shè)置host host內(nèi)部持有的是spring的TomcatEmbeddedContext
- 最后獲取TomcatWebServer并初始化卖丸,即設(shè)置LifecycleListener并且啟動(dòng)tomcat
registerListeners
- 主要是注冊(cè)ApplicationListener-當(dāng)容器初始化完成之后纺且,需要處理一些操作,比如一些數(shù)據(jù)的加載稍浆、初始化緩存载碌、特定任務(wù)的注冊(cè)等等。這個(gè)時(shí)候我們就可以使用Spring提供的ApplicationListener來進(jìn)行操作衅枫。
- 然后發(fā)布earlyApplicationEvents
finishBeanFactoryInitialization
- 設(shè)置beanFactory 的conversion service(其實(shí)作為JavaBeans PropertyEditors.的替代者 用來轉(zhuǎn)換屬性值)
- 為嵌入值(例如注釋屬性)添加String解析器嫁艇。
- 盡早初始化LoadTimeWeaverAware bean以允許盡早注冊(cè)其變換器。
- 將temporary ClassLoader設(shè)置為null
- 凍結(jié)所有的beanDefinition,不允許更改
- 實(shí)例所有非懶加載的bean對(duì)象
finishRefresh
- 清除上下文級(jí)資源緩存(例如來自掃描的ASM元數(shù)據(jù))弦撩。
- 初始化容器的lifecycle processor 比如smartLifeCycle
- 按照phase的大小依次啟動(dòng)lifecycle processor
- 發(fā)送ContextRefreshedEvent時(shí)間
- 如果LiveBeansView MBean 激活了步咪,則參與LiveBeansView MBean。
destroyBeans 摧毀所有的單例
cancelRefresh 設(shè)active標(biāo)識(shí)為false
resetCommonCaches
- 清除反射的緩存
- 清除注解的相關(guān)緩存
- Clear the internal {@code ResolvableType}/{@code SerializableTypeWrapper} cache.
- 清除classloader緩存
內(nèi)置tomcat的說明
內(nèi)置tomcat的懸疑
首先創(chuàng)建ServletWebServerFactory的bean
然后調(diào)用其getWebServer生成WebServer
然后在創(chuàng)建baseDir益楼,根據(jù)協(xié)議創(chuàng)建Connector和ProtocolHandler(協(xié)議處理器)
這個(gè)ProtocolHandler主要是設(shè)置adapter和Endpoint猾漫,而 adapter可以調(diào)用connector
adapter提供了service,prepare感凤,asyncDispatch悯周,log,checkRecycled陪竿,getDomain
其中domain是用來注冊(cè)跟這個(gè)connector關(guān)聯(lián)的Mbeans
然后創(chuàng)建service禽翼,connector,container(enigne),添加valve
下面關(guān)鍵的就來了 我們知道container的順序是engine闰挡,host锐墙,context,wrapper
我們這邊創(chuàng)建了一個(gè)TomcatEmbeddedContext解总,將spring容器塞入TomcatEmbeddedContext
同時(shí)創(chuàng)建一個(gè)WebappLoader給當(dāng)前的TomcatEmbeddedContext
創(chuàng)建一個(gè)Wrapper塞入TomcatEmbeddedContext
通過把我們spring容器包裝成ServletContextInitializer
然后配置我們的context 包括設(shè)置starter(其就是我們ServletContextInitializer的集合類)
設(shè)置Valve,ErrorPage,MimeMappings
然后我們啟動(dòng)tomcat(啟動(dòng)server)
最終我們調(diào)用ServletWebServerApplicationContext的selfInitialize贮匕,其主要是把spring容器
和servletContext 互相綁定,當(dāng)我們請(qǐng)求時(shí)候tomcat最終會(huì)調(diào)用dispatchServlet花枫,然后把spring容器設(shè)置
為該servlet的屬性刻盐,這樣就可以在該servlet使用spring提供的功能
ProtocolHandler 內(nèi)部包含一個(gè)endpoint 也就是說該協(xié)議采用
endpoint 進(jìn)行底層的socket的通信
可以把Endpoint理解 為netty的serverbootStrap
當(dāng)endpoint發(fā)現(xiàn)需要處理的socket,會(huì)創(chuàng)建一個(gè)SocketProcessor
最終會(huì)調(diào)用ProtocolHandler的process方法劳翰,該方法會(huì)創(chuàng)建一個(gè)Processor
該P(yáng)rocessor會(huì)包含adapter敦锌,其他的請(qǐng)求信息等
最終adapter會(huì)交給對(duì)應(yīng)的container
--
Valve和ContainerBackgroundProcessor
一般只會(huì)給engine啟動(dòng)一個(gè)線程去執(zhí)行ContainerBackgroundProcessor
而該任務(wù)會(huì)執(zhí)行當(dāng)前container和其子類容器的 backgroundProcess();
而 一般container的backgroundProcess不僅僅包含container本身還包含該
container的pipeline的valve的backgroundProcess
一般接受一個(gè)請(qǐng)求的流程是
Endpoint.Acceptor的acceptor線程接受到請(qǐng)求
一層層處理交給Adapter
而Adapter主要就是調(diào)用其service方法把
org.apache.coyote.Request req, org.apache.coyote.Response res
轉(zhuǎn)換為HttpServletRequest和HttpServletResponse
然后交給engine的第一個(gè)valve處理
每個(gè)容器都有一個(gè)pipeline 里面存儲(chǔ)鏈表valve
其最后一個(gè)valve都是負(fù)責(zé)連接下一個(gè)container