SpringApplication是SpringBoot的启动程序,我们通过它的run方法可以快速启动一个SpringBoot应用。
启动控制台的输出内容:
基于SpringFramework的事件机制
事件机制是SpringBoot的启动核心,在这里先介绍JDK和Spring中事件的机制和原理
JDK的事件机制
JDK中的事件机制,首先定义了一个EventObject类,所有的事件类都要继承这个类
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
public Object getSource() {
return source;
}
/**
* Returns a String representation of this EventObject.
*
* @return A a String representation of this EventObject.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
一个EventObject对应了一个EventListener监听器接口,EventListener是一个接口,没有定义任何的方法。监听器的作用是,当监听的某个事件发生改变时,则处理对应的监听器中的代码逻辑。
public interface EventListener {
}
所有的自定义监听器都必须继承EventListener。比如MouseListener,而且监听的所有事件都是MouseEvent。
public interface MouseListener extends EventListener {
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
*/
public void mouseClicked(MouseEvent e);
/**
* Invoked when a mouse button has been pressed on a component.
*/
public void mousePressed(MouseEvent e);
/**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(MouseEvent e);
/**
* Invoked when the mouse enters a component.
*/
public void mouseEntered(MouseEvent e);
/**
* Invoked when the mouse exits a component.
*/
public void mouseExited(MouseEvent e);
}
Spring中的事件机制
Spring中也给我们提供了一套事件处理机制,其中几个较为关键的接口和类分别是:
- ApplicationEvent
- ApplicationListener
- ApplicationEventPublisher
- ApplicationEventMulticaster
ApplicationEvent直接继承EventObject类
ApplicationListener继承了EventListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
ApplicationEventPublisher用来触发一个事件。调用方法publishEvent过后,事件对应的listener将会执行相应的内容
public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event. Events may be framework events
* (such as RequestHandledEvent) or application-specific events.
* @param event the event to publish
* @see org.springframework.web.context.support.RequestHandledEvent
*/
void publishEvent(ApplicationEvent event);
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an event.
* <p>If the specified {@code event} is not an {@link ApplicationEvent},
* it is wrapped in a {@link PayloadApplicationEvent}.
* @param event the event to publish
* @since 4.2
* @see PayloadApplicationEvent
*/
void publishEvent(Object event);
}
ApplicationEventMulticaster管理ApplicationListener的同时可以执行listener监听事件的方法
public interface ApplicationEventMulticaster {
/**
* Add a listener to be notified of all events.
* @param listener the listener to add
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* Add a listener bean to be notified of all events.
* @param listenerBeanName the name of the listener bean to add
*/
void addApplicationListenerBean(String listenerBeanName);
/**
* Remove a listener from the notification list.
* @param listener the listener to remove
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* Remove a listener bean from the notification list.
* @param listenerBeanName the name of the listener bean to add
*/
void removeApplicationListenerBean(String listenerBeanName);
/**
* Remove all listeners registered with this multicaster.
* <p>After a remove call, the multicaster will perform no action
* on event notification until new listeners are being registered.
*/
void removeAllListeners();
/**
* Multicast the given application event to appropriate listeners.
* <p>Consider using {@link #multicastEvent(ApplicationEvent, ResolvableType)}
* if possible as it provides a better support for generics-based events.
* @param event the event to multicast
*/
void multicastEvent(ApplicationEvent event);
/**
* Multicast the given application event to appropriate listeners.
* <p>If the {@code eventType} is {@code null}, a default type is built
* based on the {@code event} instance.
* @param event the event to multicast
* @param eventType the type of event (can be null)
* @since 4.2
*/
void multicastEvent(ApplicationEvent event, ResolvableType eventType);
}
接下来,可以实现一个基于spring的自定义事件:当感到饥饿时,通知厨师做饭
定义事件:
public class HungryEvent extends ApplicationEvent {
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public HungryEvent(Object source) {
super(source);
}
}
定义Person:
@Component
public class Person implements ApplicationEventPublisherAware {
private int hungry;
private String name;
public int getHungry() {
return hungry;
}
public void setHungry(int hungry) {
this.hungry = hungry;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void isNeedEat() {
if (this.hungry == 0) {
System.out.println("太饿了,需要吃东西");
new Thread(() -> this.applicationEventPublisher.publishEvent(new HungryEvent(this))).start();
System.out.println("通知完毕");
}
}
}
注意这里面利用spring的aware模式拿到ApplicationEventPublisher对象,在Spring里有若干个Aware,比如说ApplicationContextAware BeanFactoryAware等。
定义厨师类,实际上是一个监听器:
@Component
public class Chef implements ApplicationListener<HungryEvent> {
@Override
public void onApplicationEvent(HungryEvent event) {
if (event.getSource() instanceof Person) {
Person person = (Person) event.getSource();
System.out.println(person.getName() + "饿了,开始做饭");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("做饭完毕....开始吃吧");
}
}
}
最后实现main方法:
public class Main {
public static void main(String[] args) throws IOException, NamingException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
Person person = applicationContext.getBean(Person.class);
person.setHungry(0);
person.setName("admin");
person.isNeedEat();
}
}
输出的结果:
SpringBoot启动分析
springboot初始化分析
在SpringApplication类中,首先注意这个方法:getSpringFactoriesInstances()
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
这个方法中的SpringFactoriesLoader类,是读取META-INF/spring.factories配置文件里配置的引导对象
SpringApplication类中的ApplicationListener是spring.factories文件中获取的,用来监听SpringApplicationEvent,SpringApplicationEvent有如下子类:
1. ApplicationStartingEvent
2. ApplicationEnvironmentPreparedEvent
3. ApplicationPreparedEvent
4. ApplicationFailedEvent
5. ApplicationReadyEvent
SpringApplicaiton.run()方法分析
核心代码如下:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
首先通过 getRunListeners获取META-INF/spring.factories文件里获取所有配置的SpringApplicationRunnerListener
SpringApplicationRunner接口的作用就是在SpringBoot启动过程中完成各个阶段需要做的事情,阶段包括:程序准备启动,准备环境,ApplicationContext准备加载,程序启动完成等等。
public interface SpringApplicationRunListener {
void starting();
void environmentPrepared(ConfigurableEnvironment var1);
void contextPrepared(ConfigurableApplicationContext var1);
void contextLoaded(ConfigurableApplicationContext var1);
void started(ConfigurableApplicationContext var1);
void running(ConfigurableApplicationContext var1);
void failed(ConfigurableApplicationContext var1, Throwable var2);
}
SpringApplicationRunner有一个默认的接口实现,EventPublishingRunListener:
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
Iterator var3 = application.getListeners().iterator();
while(var3.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var3.next();
this.initialMulticaster.addApplicationListener(listener);
}
}
public int getOrder() {
return 0;
}
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
public void contextLoaded(ConfigurableApplicationContext context) {
ApplicationListener listener;
for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
listener = (ApplicationListener)var2.next();
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware)listener).setApplicationContext(context);
}
}
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
public void started(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
}
public void running(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
}
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
if (context != null && context.isActive()) {
context.publishEvent(event);
} else {
if (context instanceof AbstractApplicationContext) {
Iterator var4 = ((AbstractApplicationContext)context).getApplicationListeners().iterator();
while(var4.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var4.next();
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new EventPublishingRunListener.LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
private static class LoggingErrorHandler implements ErrorHandler {
private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);
private LoggingErrorHandler() {
}
public void handleError(Throwable throwable) {
logger.warn("Error calling ApplicationEventListener", throwable);
}
}
}
其中SimpleApplicationEventMulticaster就是前面说的执行关于SpringApplicationEvent的事件监听方法的。该类最主要作用就是通知各个阶段的listener处理对应阶段的事件。
至此,就可以大致了解springboot的启动过程了。