关联博文:
AbstractApplicationContext中refresh方法详解
Spring中refresh分析之prepareRefresh方法详解
Spring中refresh分析之obtainFreshBeanFactory方法详解
Spring中refresh分析之prepareBeanFactory方法详解
Spring中refresh分析之postProcessBeanFactory方法详解
Spring中refresh分析之invokeBeanFactoryPostProcessors方法详解
Spring中refresh分析之registerBeanPostProcessors方法详解
Spring中refresh分析之initMessageSource方法详解
Spring中refresh分析之initApplicationEventMulticaster方法详解
Spring中refresh分析之onRefresh方法详解
Spring中refresh分析之registerListeners方法详解
Spring中refresh分析之finishBeanFactoryInitialization方法详解
Spring中refresh分析之finishRefresh方法详解
接上文Spring中refresh分析之finishBeanFactoryInitialization方法详解我们分析过finishBeanFactoryInitialization后,本文分析finishRefresh方法。
方法功能梳理:
- 清理前面记录的类资源(因为已经有了
BeanDefinition
); - 初始化生命周期处理器,默认是DefaultLifecycleProcessor,并作为单例注册到容器;
- 触发DefaultLifecycleProcessor的onRefresh方法,简单来讲就是触发那些实现了Lifecycle的bean的start方法并将running状态设置为true。
- 发布事件ContextRefreshedEvent,这个玩意很重要标志着上下文刷新执行完毕
- 注册ApplicationContext到LiveBeansView内部的applicationContexts中。
- 启动webserver,处理webserver的service与connector,并触发connector的start方法;
- 发布ServletWebServerInitializedEvent事件,标志着WebServer启动完毕。
ServletWebServerApplicationContext的finishRefresh方法
@Override
protected void finishRefresh() {
//触发父类的方法
super.finishRefresh();
//启动WebServer,将WebServer的started置为true
WebServer webServer = startWebServer();
// 发布事件
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
如上所示其会首先触发父类的方法,然后启动WebServer,最后发布ServletWebServerInitializedEvent事件。
ServletWebServerInitializedEvent事件会被如下四个监听器捕捉:
0 = {RestartApplicationListener@9680}
1 = {SpringApplicationAdminMXBeanRegistrar@9681}
2 = {DelegatingApplicationListener@9682}
3 = {ServerPortInfoApplicationContextInitializer@9683}
其ServerPortInfoApplicationContextInitializer的onApplicationEvent方法将会为环境的PropertySources设置server.ports--new MapPropertySource("server.ports", new HashMap<>())
关于事件发布与捕捉可以参考博文:Spring中事件监听(通知)机制详解与实践 。
【1】super.finishRefresh
AbstractApplicationContext的finishRefresh方法
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
方法逻辑梳理如下:
- 清理前面记录的类资源(因为已经有了
BeanDefinition
); - 初始化生命周期处理器,默认是DefaultLifecycleProcessor,并作为单例注册到容器;
- 触发DefaultLifecycleProcessor的onRefresh方法,简单来讲就是触发那些实现了Lifecycle的bean的start方法并将running状态设置为true。
- 发布事件ContextRefreshedEvent,这个玩意很重要标志着上下文刷新执行完毕
- 注册ApplicationContext到LiveBeansView内部的applicationContexts中。
① clearResourceCaches
DefaultResourceLoader
是ResourceLoader
接口的默认实现,内部维护了一个ConcurrentHashMap
用来缓存class
的resource
。这里即清理前面记录的类资源(因为已经有了BeanDefinition
)。
// DefaultResourceLoader
public void clearResourceCaches() {
this.resourceCaches.clear();
}
private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);
本文这里的resourceCaches 如下所示:
② initLifecycleProcessor
顾名思义,初始化生命周期处理器。方法如下所示:
- 获取BeanFactory,本文这里是DefaultListableBeanFactory。
- 如果beanFactory有lifecycleProcessor,则触发getBean获取到bean实例赋予
this.lifecycleProcessor
。 - 如果beanFactory没有lifecycleProcessor,则实例化DefaultLifecycleProcessor然后设置beanFactory
- 将新创建的defaultProcessor 指向
this.lifecycleProcessor
- 作为单例注册到beanFactory中
- 将新创建的defaultProcessor 指向
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// lifecycleProcessor
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
③ getLifecycleProcessor().onRefresh()
其实就是调用前面我们实例化的DefaultLifecycleProcessor
的onRefresh方法。简单来讲就是触发那些实现了Lifecycle的bean的start方法并将running状态设置为true。
// DefaultLifecycleProcessor
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
这个startBeans是什么意思呢?就是触发那些实现了Lifecycle的bean的start方法。
private void startBeans(boolean autoStartupOnly) {
// 获取实现了Lifecycle的bean
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
//
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
// 确定给定bean的生命周期阶段
int phase = getPhase(bean);
//获取其所属的生命周期组
LifecycleGroup group = phases.get(phase);
if (group == null) {
// 如果group为null则初始化一个LifecycleGroup 并 放入phases中
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
//将当前bean添加到生命周期组中 List<LifecycleGroupMember> members
group.add(beanName, bean);
}
});
// 如果不为空,则按照生命周期阶段,触发每个生命周期组中bean的start方法
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
④ registerApplicationContext
// LiveBeansView
static void registerApplicationContext(ConfigurableApplicationContext applicationContext) {
// spring.liveBeansView.mbeanDomain 本文这里mbeanDomain是""
String mbeanDomain = applicationContext.getEnvironment().getProperty(MBEAN_DOMAIN_PROPERTY_NAME);
if (mbeanDomain != null) {
synchronized (applicationContexts) {
if (applicationContexts.isEmpty()) {
try {
// JmxMBeanServer
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
// 本文这里是""
applicationName = applicationContext.getApplicationName();
server.registerMBean(new LiveBeansView(),
// application
new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationName));
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to register LiveBeansView MBean", ex);
}
}
// 将上下文放到applicationContexts中
applicationContexts.add(applicationContext);
}
}
}
// applicationContexts如下
private static final Set<ConfigurableApplicationContext> applicationContexts = new LinkedHashSet<>();
【2】startWebServer
ServletWebServerApplicationContext的startWebServer方法如下所示,其是关于tomcat中service与connector的处理。
- 会将connector放到StandardService的
protected Connector connectors[] = new Connector[0];
- 为connector绑定service;
- 触发connector的start方法
- 检测connector的状态是否为LifecycleState.FAILED
// ServletWebServerApplicationContext
private WebServer startWebServer() {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.start();
}
return webServer;
}
// TomcatWebServer
@Override
public void start() throws WebServerException {
synchronized (this.monitor) {
if (this.started) {
return;
}
try {
addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
performDeferredLoadOnStartup();
}
// 检测connector的状态是否为LifecycleState.FAILED
checkThatConnectorsHaveStarted();
this.started = true;
logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"
+ getContextPath() + "'");
}
catch (ConnectorStartFailedException ex) {
stopSilently();
throw ex;
}
catch (Exception ex) {
if (findBindException(ex) != null) {
throw new PortInUseException(this.tomcat.getConnector().getPort());
}
throw new WebServerException("Unable to start embedded Tomcat server", ex);
}
finally {
//StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]
Context context = findContext();
ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
}
}
addPreviouslyRemovedConnectors
获取tomcat server的service,及connectors ,然后逐个为connector绑定service并触发connector的start方法。
private void addPreviouslyRemovedConnectors() {
Service[] services = this.tomcat.getServer().findServices();
for (Service service : services) {
// serviceConnectors只是一个HashMap
Connector[] connectors = this.serviceConnectors.get(service);
if (connectors != null) {
for (Connector connector : connectors) {
//添加到service
service.addConnector(connector);
if (!this.autoStart) {
stopProtocolHandler(connector);
}
}
//从map中移除
this.serviceConnectors.remove(service);
}
}
}
// Add a new Connector to the set of defined Connectors, and associate it
//with this Service's Container
public void addConnector(Connector connector) {
synchronized (connectorsLock) {
connector.setService(this);
Connector results[] = new Connector[connectors.length + 1];
System.arraycopy(connectors, 0, results, 0, connectors.length);
results[connectors.length] = connector;
connectors = results;
}
try {
if (getState().isAvailable()) {
connector.start();
}
} catch (LifecycleException e) {
throw new IllegalArgumentException(
sm.getString("standardService.connector.startFailed", connector), e);
}
// Report this property change to interested listeners
support.firePropertyChange("connector", null, connector);
}
关于service、connector如下图所示:
performDeferredLoadOnStartup
如下所示,触发TomcatEmbeddedContext的deferredLoadOnStartup方法。
// TomcatWebServer
private void performDeferredLoadOnStartup() {
try {
for (Container child : this.tomcat.getHost().findChildren()) {
if (child instanceof TomcatEmbeddedContext) {
((TomcatEmbeddedContext) child).TomcatEmbeddedContext();
}
}
}
catch (Exception ex) {
if (ex instanceof WebServerException) {
throw (WebServerException) ex;
}
throw new WebServerException("Unable to start embedded Tomcat connectors", ex);
}
}
TomcatEmbeddedContext
的deferredLoadOnStartup
方法如下所示,其会获取到容器关联的children。对children进行遍历获取其loadOnStartup值,如果大于0则有选择性的放到grouped中。
void deferredLoadOnStartup() throws LifecycleException {
doWithThreadContextClassLoader(getLoader().getClassLoader(),
() -> getLoadOnStartupWrappers(findChildren()).forEach(this::load));
}
//这里会触发Runnable 的 run方法
private void doWithThreadContextClassLoader(ClassLoader classLoader, Runnable code) {
ClassLoader existingLoader = (classLoader != null) ? ClassUtils.overrideThreadContextClassLoader(classLoader)
: null;
try {
code.run();
}
finally {
if (existingLoader != null) {
ClassUtils.overrideThreadContextClassLoader(existingLoader);
}
}
}
private Stream<Wrapper> getLoadOnStartupWrappers(Container[] children) {
Map<Integer, List<Wrapper>> grouped = new TreeMap<>();
for (Container child : children) {
Wrapper wrapper = (Wrapper) child;
// 获取其loadOnStartup值
int order = wrapper.getLoadOnStartup();
if (order >= 0) {
grouped.computeIfAbsent(order, (o) -> new ArrayList<>()).add(wrapper);
}
}
return grouped.values().stream().flatMap(List::stream);
}
本文这里获取到的tomcat container的children如下所示:
0 = {StandardWrapper@9088} "StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[default]"
1 = {StandardWrapper@9090} "StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]"
最后把Map<Integer, List<Wrapper>> grouped
中的values以流的方式返回一个list。
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流