接上文Spring中refresh分析之finishBeanFactoryInitialization方法详解我们分析过finishBeanFactoryInitialization后,本文分析finishRefres方法。
方法功能梳理:
清理前面记录的类资源(因为已经有了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<>())
【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中
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> grouped
中的values以流的方式返回一个list。
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流