spring
aop
spring boot
加载类的两种方式
spring bean
注解
@Service @Component @Bean ...applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="test" class="com.example.dao.TestDaoImpl"/> </beans>
SpringFactoriesLoader 在resources目录下加上META-INF/spring.factories:
org.springframework.context.ApplicationListener=kyoo.order.listener.MyApplicationListener主要支持类:
- BootstrapRegistryInitializer
- ApplicationContextInitializer
- ApplicationListener
- SpringApplicationRunListener
spring boot应用启动过程
状态图
SpringApplicationRunListener类明确标出了spring应用启动的状态阶段:
stateDiagram-v2
direction LR
[*] --> starting
starting --> environmentPrepared
environmentPrepared --> contextPrepared
environmentPrepared --> failed
contextPrepared --> contextLoaded
contextPrepared --> failed
contextLoaded --> started
contextLoaded --> failed
started --> ready
started --> failed
failed --> [*]
ready --> [*]
核心代码
org.springframework.boot.SpringApplication类的run方法:
public ConfigurableApplicationContext run(String... args) {
Startup startup = SpringApplication.Startup.create();
if (this.properties.isRegisterShutdownHook()) {
shutdownHook.enableShutdownHookAddition();
}
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
Duration timeTakenToStarted = startup.started();
if (this.properties.isLogStartupInfo()) {
(new StartupInfoLogger(this.mainApplicationClass, environment)).logStarted(this.getApplicationLog(), startup);
}
listeners.started(context, timeTakenToStarted);
this.callRunners(context, applicationArguments);
} catch (Throwable ex) {
throw this.handleRunFailure(context, ex, listeners);
}
try {
if (context.isRunning()) {
listeners.ready(context, startup.ready());
}
return context;
} catch (Throwable ex) {
throw this.handleRunFailure(context, ex, (SpringApplicationRunListeners)null);
}
}
构造SpringApplication
通过SpringFactoriesLoader加载下面初始化器:
- BootstrapRegistryInitializer 用来初始化启动上下文
- ApplicationContextInitializer 应用上下文初始化器
- ApplicationListener 事件监听器
初始化启动上下文
通过BootstrapRegistryInitializer来初始化启动上下文
触发事件starting
解析应用配置
通过prepareEnvironment方法解析应用配置
触发事件environmentPrepared
创建并初始化上下文
创建上下文并调用ApplicationContextInitializer来初始化
触发事件contextPrepared和contextLoaded
刷新上下文
调用AbstractApplicationContext的refresh方法刷新上下文
触发事件contextRefreshed和started
最后阶段
同步执行所有runner
触发事件ready
bean的加载过程
web项目会用ServletWebServerApplicationContextFactory创建出AnnotationConfigServletWebServerApplicationContext
AnnotationConfigServletWebServerApplicationContext使用ClassPathBeanDefinitionScanner来扫描类,然后用AnnotatedBeanDefinitionReader来读取注解类型的bean并注册到beanFactory中
然后执行AbstractApplicationContext的refresh方法:
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
this.startupShutdownThread = Thread.currentThread();
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 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);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 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 (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();
}
}
refresh方法生成bean的流程图:
sequenceDiagram
SpringApplication->>+AbstractApplicationContext: refresh
AbstractApplicationContext->>+AbstractApplicationContext: finishBeanFactoryInitialization
AbstractApplicationContext->>+DefaultListableBeanFactory: preInstantiateSingletons
loop
DefaultListableBeanFactory->>+DefaultListableBeanFactory: getSingleton
end
DefaultListableBeanFactory-->>-AbstractApplicationContext:
AbstractApplicationContext-->>-SpringApplication:
getSingleton最后会调用AbstractBeanFactory的doGetBean方法,doGetBean会先遍历自己依赖的bean,并检查依赖的bean是否依赖自己(就是检查循环依赖,默认如果出现循环依赖就抛出循环依赖异常),如果不依赖自己就先获取依赖的bean,就是先初始化自己依赖的bean
bean生命周期
spring web
web三个组件
- Servlet
- Filter
- EventListener
注册方式:
filter
@Component public class MyFilter implements Filter {} 或 @Bean public FilterRegistrationBean<Filter> myFilterRegistration() { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new MyAnotherFilter()); return filterRegistrationBean; } 或 @ServletComponentScan("kyoo.order.filter") public class MyWebConfig implements WebMvcConfigurer {} ... @WebFilter public class MyThirdFilter implements Filter {}listener
@Component public class MyServletContextListener implements ServletContextListener {} 或 @Bean public ServletListenerRegistrationBean<ServletContextListener> myServletListenerRegistration() { ServletListenerRegistrationBean<ServletContextListener> registrationBean = new ServletListenerRegistrationBean<>(new MySecondServletContextListener()); return registrationBean; } 或 @ServletComponentScan("kyoo.order.listener") public class MyWebConfig implements WebMvcConfigurer {} ... @WebListener public class MyThirdServletListener implements ServletContextListener {}
序列图
一个http请求执行的序列图:
sequenceDiagram
Tomcat->>+ApplicationFilterChain: doFilter
ApplicationFilterChain->>+Filter: doFilter
Filter->>+DispatcherServlet: doService
DispatcherServlet-->>-Filter: Void
Filter-->>-ApplicationFilterChain: Void
ApplicationFilterChain-->>-Tomcat: HttpServletResponse
核心类DispatcherServlet
实际上是一个HttpServlet,绑定了路径/,由DispatcherServletAutoConfiguration类配置
核心代码:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Determine handler adapter and invoke the handler.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new ServletException("Handler dispatch failed: " + err, err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new ServletException("Handler processing failed: " + err, err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
asyncManager.setMultipartRequestParsed(multipartRequestParsed);
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed || asyncManager.isMultipartRequestParsed()) {
cleanupMultipart(processedRequest);
}
}
}
}
自定义配置类WebMvcConfigurer
常用配置项:
- addInterceptors 配置拦截器
- addCorsMappings 配置跨域
- configureMessageConverters 配置body解析器
- getValidator 配置校验器

