上一篇博客写了SpringApplication.run(AuthServiceApplication.class, args); 的SpringApplication初始化,这一篇就写一下后面的run方法。
前言:写本篇博客前,我自己一步步的点进方法去看代码,乱糟糟的也不知道,代码都在做什么,反过来调过去的看了许久之后,发现,要想看懂SpringApplication的框架,首先最应该先了解的是 观察者模式,因为,在我的理解和查看中,又查阅不少博客,发现框架整体是用观察者来加载各个组件,达到灵活插拔的效果。观察者模式,请不太清楚的同学自行查阅,我这里给出简单的例子,就不再多做解释。
1 public class BaseEvent extends EventObject { 2 String name; 3 4 public BaseEvent(Object source, String name) { 5 super(source); 6 this.name = name; 7 } 8 9 public String getName() { 10 return name; 11 } 12 } 13 14 public interface BaseListener<T extends BaseEvent> extends EventListener { 15 void doEvent(T t); 16 } 17 public interface EventPublisher<T extends BaseEvent> { 18 abstract void publish(T event); 19 } 20 public class Event extends BaseEvent { 21 public Event(Object source, String name) { 22 super(source, name); 23 } 24 } 25 public class Listener implements BaseListener<Event> { 26 27 private String name; 28 29 public Listener(String name) { 30 this.name = name; 31 } 32 public Listener() { 33 } 34 @Override 35 public void doEvent(Event event) { 36 System.out.println("我是监听者:"+this.name+",我监控到来自:"+ event.getName()+",的event"); 37 } 38 39 } 40 public class BaseEventPublisher<T extends BaseEvent> implements EventPublisher { 41 42 List<BaseListener<T>> listenerList = new ArrayList<>(); 43 44 public List<BaseListener<T>> getListenerList() { 45 return listenerList; 46 } 47 48 @Override 49 public void publish(BaseEvent event) { 50 if (!CollectionUtils.isEmpty(listenerList)) { 51 for (BaseListener listener:listenerList) { 52 listener.doEvent((T) event); 53 } 54 } 55 } 56 } 57 58 59 BaseEvent eventA = new Event("","eventA"); 60 BaseEventPublisher publisher = new BaseEventPublisher(); 61 BaseListener<Event> listenerA = new Listener("listenerA"); 62 BaseListener<Event> listenerB = new Listener("listenerB"); 63 publisher.getListenerList().add(listenerA); 64 publisher.getListenerList().add(listenerB); 65 publisher.publish(eventA);
大家可以自行运行一下,理解一下观察者模式的思维。
--------------------
下面就写一下我自己看源码的理解
1 public ConfigurableApplicationContext run(String... args) { 2 StopWatch stopWatch = new StopWatch();//用来输出所包含的代码运行完消耗的时间,可自行查阅相关用法,不再此赘述 3 stopWatch.start(); 4 ConfigurableApplicationContext context = null; 5 Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); 6 configureHeadlessProperty(); 7 SpringApplicationRunListeners listeners = getRunListeners(args);//获取上面博客所述的配置在spring.factories的监听者 8 listeners.starting();//这里就开始了观察者模式 9 try { 10 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 11 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);//准备运行的环境信息 12 configureIgnoreBeanInfo(environment);//配置忽略 13 Banner printedBanner = printBanner(environment); 14 context = createApplicationContext();//创建上下文 15 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, 16 new Class[] { ConfigurableApplicationContext.class }, context); 17 prepareContext(context, environment, listeners, applicationArguments, printedBanner);//准备上下文 18 refreshContext(context);//刷新上下文 19 afterRefresh(context, applicationArguments); 20 stopWatch.stop(); 21 if (this.logStartupInfo) { 22 new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); 23 } 24 listeners.started(context);//启动上下文 25 callRunners(context, applicationArguments);//通知所有的线程开始运行 26 } 27 catch (Throwable ex) { 28 handleRunFailure(context, ex, exceptionReporters, listeners); 29 throw new IllegalStateException(ex); 30 } 31 32 try { 33 listeners.running(context);//运行 34 } 35 catch (Throwable ex) { 36 handleRunFailure(context, ex, exceptionReporters, null); 37 throw new IllegalStateException(ex); 38 } 39 return context; 40 }
上面代码段,先着重讲一下第八行,listeners.starting();因为后面很多代码内部都和这一行运行的代码类似
void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
1 public void starting() { 2 this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args)); 3 }
initialMulticaster,多路广播器。通知所有监听者,接到广播的就要运行了。multicastEvent代码如下
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
下面进入invokeListener
1 private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { 2 try { 3 listener.onApplicationEvent(event);//划重点 4 } 5 catch (ClassCastException ex) { 6 String msg = ex.getMessage(); 7 if (msg == null || matchesClassCastMessage(msg, event.getClass())) { 8 // Possibly a lambda-defined listener which we could not resolve the generic event type for 9 // -> let's suppress the exception and just log a debug message. 10 Log logger = LogFactory.getLog(getClass()); 11 if (logger.isTraceEnabled()) { 12 logger.trace("Non-matching event type for listener: " + listener, ex); 13 } 14 } 15 else { 16 throw ex; 17 } 18 } 19 }
listener.onApplicationEvent(event);此方法运行实现了 org.springframework.context.ApplicationListener类的onApplicationEvent方法。
整个框架多处使用,广播和监听机制,*的配置监听者。各个组件,配置自己的监听者,达到*扩展的目的。