Spring 中最核心的方法就是 refresh,负责完成 Bean 注册、Bean 实例化、AOP
1. refresh()
ClassPathXmlApplicationContext # ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
AbstractApplicationContext # refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 刷新上下文环境,(如设置启动时间,对系统属性、环境变量进行准备、验证),为容器初始化做准备
prepareRefresh();
/**
* 创建 BeanFactory 对象,并解析 XML。经过这个函数后,ApplicationContext 就拥有了 BeanFactory 的全部功能。
* 在 xml 解析时,会封装 xml 标签成 BeanDefinition 对象。包括 2 类标签解析:
* 1. 默认标签解析:bean、import、alias、beans
* 2. 自定义标签解析,如:<context:component-scan base-package="com.xmustang.bean" />
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 给 beanFactory 设置一些属性值,如增加对 SpEL 支持
prepareBeanFactory(beanFactory);
try {
// 供子类覆写
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 实例化所有实现了 BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor 接口的类,
// 并完成这两个接口中的方法调用
invokeBeanFactoryPostProcessors(beanFactory);
// 实例化所有实现了 BeanPostProcessor 接口的类,并加入到 BeanFactory 中,
// 这些 BeanPostProcessor 在 bean 创建过程中调用
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 初始化 MessageSource,主要是完成国际化处理
initMessageSource();
// 初始化事件管理类
initApplicationEventMulticaster();
// 供子类覆写
onRefresh();
// 在所有 Bean 中查找 ApplicationListener,注册到事件管理类中
registerListeners();
/*
* 这个方法完成包括:
* 1. bean 实例化(包含创建对象、IOC)
* 2. AOP
*/
finishBeanFactoryInitialization(beanFactory);
// 完成刷新过程,通知生命周期处理器 lifecycleProcessor 刷新过程,同时发出 ContextRefreshEvent 通知
// 在 Spring 中还提供了 Lifecycle 接口,Lifecycle 中包含 start/stop 方法,实现此接口后,
// Spring 会保证在启动时调用其 start 方法开始生命周期,在关闭时调用其 stop 方法结束生命周期,
// 通常用来配置后台程序,在启动后一直运行(如对 MQ 进行轮询等)
finishRefresh();
} catch (BeansException 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 {
// Reset common introspection caches in Spring's core, since we might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
以下讲解 refresh 中不是太重要的方法,重要的方法留给后续分章节讲解:
2. prepareRefresh()
AbstractApplicationContext # prepareRefresh
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
} else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 留给子类覆盖,用户可根据自身的需要重写 initPropertySources(),并在方法中进行个性化的属性处理及设置
initPropertySources();
// 验证需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
3. prepareBeanFactory(beanFactory)
/**
* 主要进行下面几个方面的扩展:
* 1. 增加对 SpEL 语言的支持
* 2. 增加对属性编辑器的支持
* 3. 增加对一些内置类,如 EnvironmentAware、MessageSourceAware 信息注入
* 4. 设置依赖功能可忽略的接口
* 5. 设置一些固定依赖的属性
* 6. 增加 AspectJ 的支持
* 7. 将相关环境变量及属性注册为单例模式
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 的 classLoader 为当前 context 的 classLoader
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
// 设置 beanFactory 的表达式语言处理器,Spring 3 增加了表达式语言的支持
// 默认可使用 #{bean.xxx} 的形式来调用相关属性值
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
// 为 BeanFactory 增加了一个默认的 propertyEditor,这个主要是对 bean 的属性等设置管理的一个工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加 BeanPostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 设置几个忽略自动装配的接口。
// Spring 将 ApplicationContextAwareProcessor 注册后,
// 在 invokeAwareInterfaces 中间接调用的 Aware 类已经不是普通的 bean 了,
// 如 ResourceLoaderAware、ApplicationEventPublisherAware 等,当然需要在做 bean 依赖注入时忽略它们。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
// 设置几个自动装配的特殊规则
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 增加对 AspectJ 的支持
if (!IN_NATIVE_IMAGE && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 添加默认的系统环境 bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
4. initMessageSource()
AbstractApplicationContext # initMessageSource
/**
* Spring 使用硬编码的方式硬性规定了自定义资源文件 beanName 必须为 messageSource
*/
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
// 如果在配置中已经配置了 messageSource,那么将 messageSource 提取并记录在 this.messageSource 中
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
} else {
// Use empty MessageSource to be able to accept getMessage calls.
// 如果用户并没有定义配置文件,那么使用 DelegatingMessageSource
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
5. Spring 事件
Spring 事件使用的是观察者设计模式,观察者设计模式用于异步解耦。
Spring 提供了下面 5 种标准事件:
- ContextRefreshedEvent:在调用 ConfigurableApplicationContext 接口中的 refresh() 触发
- ContextStartedEvent:在调用 ConfigurableApplicationContext 接口中的 start() 触发
- ContextStoppedEvent:在调用 ConfigurableApplicationContext 接口中的 stop() 触发
- ContextClosedEvent:当 ApplicationContext 被关闭时触发该事件。容器被关闭时,其管理的所有单例 Bean 都被销毁
- RequestHandlerEvent:在 Web 应用中,当一个 Http 请求结束时触发该事件
5.1 事件示例
public class MyApplicationEvent extends ApplicationEvent {
public MyApplicationEvent(Object source) {
super(source);
}
}
@Component
public class MyEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof MyApplicationEvent) {
System.out.println("receive MyApplicationEvent:" + event.getSource());
}
if (event instanceof ContextRefreshedEvent) {
System.out.println("receive ContextRefreshedEvent:" + event.getSource());
}
if (event instanceof ContextStartedEvent) {
System.out.println("receive ContextStartedEvent:" + event.getSource());
}
if (event instanceof ContextStoppedEvent) {
System.out.println("receive ContextStoppedEvent:" + event.getSource());
}
if (event instanceof ContextClosedEvent) {
System.out.println("receive ContextClosedEvent:" + event.getSource());
}
if (event instanceof RequestHandledEvent) {
System.out.println("receive RequestHandledEvent:" + event.getSource());
}
}
}
@Component("publishEvent")
public class MyPublishEvent implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void publish(String msg) {
applicationEventPublisher.publishEvent(new MyApplicationEvent(msg));
}
}
<!-- Spring 事件 begin -->
<context:component-scan base-package="com.mustang.event"/>
<!-- Spring 事件 end -->
测试:
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
MyPublishEvent myPublishEvent = (MyPublishEvent) context.getBean("publishEvent");
// receive MyApplicationEvent:myEvent
myPublishEvent.publish("myEvent");
// receive ContextRefreshedEvent:org.springframework.context.support.ClassPathXmlApplicationContext@13969fbe, started on Wed Jun 23 16:56:06 CST 2021
context.refresh();
// receive ContextStartedEvent:org.springframework.context.support.ClassPathXmlApplicationContext@13969fbe, started on Wed Jun 23 16:56:06 CST 2021
context.start();
// receive ContextStoppedEvent:org.springframework.context.support.ClassPathXmlApplicationContext@13969fbe, started on Wed Jun 23 16:56:06 CST 2021
context.stop();
// receive ContextClosedEvent:org.springframework.context.support.ClassPathXmlApplicationContext@13969fbe, started on Wed Jun 23 16:56:06 CST 2021
context.close();
}
}
5.2 initApplicationEventMulticaster()
AbstractApplicationContext # initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果用户没有自定义事件广播器,那么使用默认的 ApplicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {// 如果用户自定义了事件广播器,那么使用用户自定义的事件广播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
5.3 registerListeners()
AbstractApplicationContext # registerListeners
protected void registerListeners() {
// 硬编码方式注册的监听器处理
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 配置文件注册的监听器处理:获取实现了 ApplicationListener 接口的类名称
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
// 多播事件,事件执行
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
SimpleApplicationEventMulticaster # multicastEvent
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
SimpleApplicationEventMulticaster # multicastEvent
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 遍历所有监听器,并使用监听器中的 onApplicationEvent 方法进行监听事件的处理。
// 对于每个监听器来说,都可以获取到产生的事件,但是否进行处理则由事件监听器来决定:void onApplicationEvent(E event);
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
} else {
invokeListener(listener, event);
}
}
}
SimpleApplicationEventMulticaster # invokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
doInvokeListener(listener, event);
}
}
SimpleApplicationEventMulticaster # doInvokeListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
} catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
} else {
throw ex;
}
}
}