调用SpringApplication
实例的run
方法
org.springframework.boot.StringApplication
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
记录开始时间
long startTime = System.nanoTime();
创建引导上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
— createBootstrapContext start
org.springframework.boot.StringApplication
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
— createBootstrapContext end
方法除了创建默认的上下文实例外,还会遍历引导注册器初始化器并调用其初始化方法
声明应用上下文
ConfigurableApplicationContext context = null;
配置Headless模式
configureHeadlessProperty();
— configureHeadlessProperty start
org.springframework.boot.StringApplication
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
private boolean headless = true;
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
— configureHeadlessProperty end
Headless模式是缺少显示设备,键盘或鼠标时的系统配置,通过系统参数java.awt.headless
设定
缺省时默认启用
获取运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
— getRunListeners start
org.springframework.boot.StringApplication
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
创建参数类型数组
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
创建并返回运行监听器集合实例
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
org.springframework.boot.StringApplication
private static final Log logger = LogFactory.getLog(SpringApplication.class);
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
获取org.springframework.boot.SpringApplicationRunListener
实例
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)
得到唯一实例org.springframework.boot.context.event.EventPublishingRunListener
—— EventPublishingRunListener start
org.springframework.boot.context.event.EventPublishingRunListener
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();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
创建事件投掷器
this.initialMulticaster = new SimpleApplicationEventMulticaster();
遍历应用的监听器集合并添加至事件投掷器
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
——— addApplicationListener start
org.springframework.context.event.AbstractApplicationEventMulticaster
private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.defaultRetriever) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
获取代理的单一目标实例
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
———— getSingletonTarget start
org.springframework.aop.framework.AopProxyUtils
@Nullable
public static Object getSingletonTarget(Object candidate) {
if (candidate instanceof Advised) {
TargetSource targetSource = ((Advised) candidate).getTargetSource();
if (targetSource instanceof SingletonTargetSource) {
return ((SingletonTargetSource) targetSource).getTarget();
}
}
return null;
}
———— getSingletonTarget end
判断为org.springframework.context.ApplicationListener
后从默认检索器中移除
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
将代理目标移除,避免监听器被二次调用
添加至默认检索器中
this.defaultRetriever.applicationListeners.add(listener);
清理检索器缓存
this.retrieverCache.clear();
——— addApplicationListener end
—— EventPublishingRunListener end
applicationStartup
用于供核心容器及其基础设施组件使用,在应用程序启动期间标记步骤,并收集有关执行上下文或其处理时间的数据
org.springframework.core.metrics.ApplicationStartup
ApplicationStartup DEFAULT = new DefaultApplicationStartup();
SpringApplication
实例初始化时创建org.springframework.core.metrics.ApplicationStartup
接口默认实现类org.springframework.core.metrics.DefaultApplicationStartup
的实例
DefaultApplicationStartup
对接口方法均为空实现,并无逻辑
创建应用运行监听器集合实例
——— SpringApplicationRunListeners start
org.springframework.boot.SpringApplicationRunListeners
private final Log log;
private final List<SpringApplicationRunListener> listeners;
private final ApplicationStartup applicationStartup;
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners,
ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
this.applicationStartup = applicationStartup;
}
——— SpringApplicationRunListeners end
— getRunListeners end
启动运行监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);
— starting start
org.springframework.boot.SpringApplicationRunListeners
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
—— doWithListeners start
org.springframework.boot.SpringApplicationRunListeners
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
Consumer<StartupStep> stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
创建启动步骤实例
StartupStep step = this.applicationStartup.start(stepName); // DefaultStartupStep
上文说过,DefaultStartupStep
相关方法均为空实现,此处org.springframework.core.metrics.DefaultApplicationStartup$DefaultStartupStep
的相关方法也是空实现
监听器处理
this.listeners.forEach(listenerAction);
listenerAction
即上述lambda
表达式(listener) -> listener.starting(bootstrapContext)
当下只有一个运行监听器org.springframework.boot.context.event.EventPublishingRunListener
——— starting start
org.springframework.boot.context.event.EventPublishingRunListener
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
创建开始事件实例
new ApplicationStartingEvent(bootstrapContext, this.application, this.args)
———— ApplicationStartingEvent start
org.springframework.boot.context.event.ApplicationStartingEvent
private final ConfigurableBootstrapContext bootstrapContext;
public ApplicationStartingEvent(ConfigurableBootstrapContext bootstrapContext, SpringApplication application,
String[] args) {
super(application, args);
this.bootstrapContext = bootstrapContext;
}
查看父类构造方法
————— SpringApplicationEvent start
org.springframework.boot.context.event.SpringApplicationEvent
private final String[] args;
public SpringApplicationEvent(SpringApplication application, String[] args) {
super(application);
this.args = args;
}
查看父类构造方法
—————— ApplicationEvent start
org.springframework.context.ApplicationEvent
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
查看父类构造方法
——————— EventObject start
java.util.EventObject
protected transient Object source;
public EventObject(Object var1) {
if (var1 == null) {
throw new IllegalArgumentException("null source");
} else {
this.source = var1;
}
}
——————— EventObject end
—————— ApplicationEvent end
————— SpringApplicationEvent end
———— ApplicationStartingEvent end
播送事件
———— multicastEvent start
org.springframework.context.event.SimpleApplicationEventMulticaster
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
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);
}
}
}
获取事件类型
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
————— resolveDefaultEventType start
org.springframework.context.event.SimpleApplicationEventMulticaster
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
org.springframework.core.ResolvableType
封装了java.lang.reflect.Type
,提供了方法访问其超类、接口和泛型,并可将他们转为java.lang.Class
—————— forInstance start
org.springframework.core.ResolvableType
public static ResolvableType forInstance(Object instance) {
Assert.notNull(instance, "Instance must not be null");
if (instance instanceof ResolvableTypeProvider) {
ResolvableType type = ((ResolvableTypeProvider) instance).getResolvableType();
if (type != null) {
return type;
}
}
return ResolvableType.forClass(instance.getClass());
}
先判断当前实例类是否实现org.springframework.core.ResolvableTypeProvider
接口,若实现了接口,可直接调用ResolvableType getResolvableType()
方法返回类型,否则调用public static ResolvableType forClass(@Nullable Class<?> clazz)
方法
——————— forClass start
org.springframework.core.ResolvableType
public static ResolvableType forClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz);
}
查看构造方法
org.springframework.core.ResolvableType
/**
* The underlying Java type being managed.
*/
private final Type type;
/**
* Optional provider for the type.
*/
@Nullable
private final TypeProvider typeProvider;
/**
* The {@code VariableResolver} to use or {@code null} if no resolver is available.
*/
@Nullable
private final VariableResolver variableResolver;
/**
* The component type for an array or {@code null} if the type should be deduced.
*/
@Nullable
private final ResolvableType componentType;
@Nullable
private final Integer hash;
@Nullable
private Class<?> resolved;
private ResolvableType(@Nullable Class<?> clazz) {
this.resolved = (clazz != null ? clazz : Object.class);
this.type = this.resolved;
this.typeProvider = null;
this.variableResolver = null;
this.componentType = null;
this.hash = null;
}
——————— forClass end
—————— forInstance end
————— resolveDefaultEventType end
获取任务执行器
Executor executor = getTaskExecutor(); // null
————— getTaskExecutor start
org.springframework.context.event.AbstractApplicationEventMulticaster
@Nullable
private Executor taskExecutor;
@Nullable
protected Executor getTaskExecutor() {
return this.taskExecutor;
}
————— getTaskExecutor end
当前未创建执行器
获取应用监听器集合并遍历
for (ApplicationListener<?> listener : getApplicationListeners(event, type))
获取监听器集合
————— getApplicationListeners start
org.springframework.context.event.SimpleApplicationEventMulticaster
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Potential new retriever to populate
CachedListenerRetriever newRetriever = null;
// Quick check for existing entry on ConcurrentHashMap
CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);
if (existingRetriever == null) {
// Caching a new ListenerRetriever if possible
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
newRetriever = new CachedListenerRetriever();
existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
if (existingRetriever != null) {
newRetriever = null; // no need to populate it in retrieveApplicationListeners
}
}
}
if (existingRetriever != null) {
Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
if (result != null) {
return result;
}
// If result is null, the existing retriever is not fully populated yet by another thread.
// Proceed like caching wasn't possible for this current local attempt.
}
return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
获取事件源
Object source = event.getSource(); // SpringApplication
由上文的构造方法可知,此处event
即之前创建的org.springframework.boot.context.event.ApplicationStartingEvent
实例
source
即当前应用实例SpringApplication
获取源类型
Class<?> sourceType = (source != null ? source.getClass() : null);
创建缓存键
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
—————— ListenerCacheKey start
org.springframework.context.event.AbstractApplicationEventMulticaster$ListenerCacheKey
private final ResolvableType eventType;
@Nullable
private final Class<?> sourceType;
public ListenerCacheKey(ResolvableType eventType, @Nullable Class<?> sourceType) {
Assert.notNull(eventType, "Event type must not be null");
this.eventType = eventType;
this.sourceType = sourceType;
}
—————— ListenerCacheKey end
声明新的监听器检索器
// Potential new retriever to populate
CachedListenerRetriever newRetriever = null;
获取已存在的监听器检索器
// Quick check for existing entry on ConcurrentHashMap
CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey); // null
判断是否已存在监听器检索器
if (existingRetriever == null)
初始没有监听器检索器,尝试创建检索器实例
判断是否创建新的检索器
// Caching a new ListenerRetriever if possible
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))))
即判断event
类和source
类是否可被安全的缓存
—————— isCacheSafe start
org.springframework.util.ClassUtils
public static boolean isCacheSafe(Class<?> clazz, @Nullable ClassLoader classLoader) {
Assert.notNull(clazz, "Class must not be null");
try {
ClassLoader target = clazz.getClassLoader();
// Common cases
if (target == classLoader || target == null) {
return true;
}
if (classLoader == null) {
return false;
}
// Check for match in ancestors -> positive
ClassLoader current = classLoader;
while (current != null) {
current = current.getParent();
if (current == target) {
return true;
}
}
// Check for match in children -> negative
while (target != null) {
target = target.getParent();
if (target == classLoader) {
return false;
}
}
}
catch (SecurityException ex) {
// Fall through to loadable check below
}
// Fallback for ClassLoaders without parent/child relationship:
// safe if same Class can be loaded from given ClassLoader
return (classLoader != null && isLoadable(clazz, classLoader));
}
判断类不为空
Assert.notNull(clazz, "Class must not be null");
获取类的加载器
ClassLoader target = clazz.getClassLoader();
返回null为根类加载器,由底层语言编写,无法获得其引用
判断当前类的类加载器是否为给定类加载器或根类加载器
if (target == classLoader || target == null) {
return true;
}
判断给定类加载器是否为空
if (classLoader == null) {
return false;
}
判断给定类加载器是否为当前类的类加载器的子级
ClassLoader current = classLoader;
while (current != null) {
current = current.getParent();
if (current == target) {
return true;
}
}
判断给定类加载器是否为当前类的类加载器的父级
while (target != null) {
target = target.getParent();
if (target == classLoader) {
return false;
}
}
当给定类加载器和当前类的类加载器没有父子级关系时,判断是否可加载
return (classLoader != null && isLoadable(clazz, classLoader));
——————— isLoadable start
org.springframework.util.ClassUtils
private static boolean isLoadable(Class<?> clazz, ClassLoader classLoader) {
try {
return (clazz == classLoader.loadClass(clazz.getName()));
// Else: different class with same name found
}
catch (ClassNotFoundException ex) {
// No corresponding class found at all
return false;
}
}
——————— isLoadable end
总结,isCacheSafe
方法基于双亲委派加载机制,判断给定的类加载器是否能加载到给定类
—————— isCacheSafe end
当前beanClassLoader
为null
创建新检索器
newRetriever = new CachedListenerRetriever();
缓存检索器
existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever); // null
若当前键已缓存,置空
if (existingRetriever != null) {
newRetriever = null; // no need to populate it in retrieveApplicationListeners
}
检索器实例已存在时,当前实例冗余
若检索器已存在且检索器获取的的监听器集合不为空,直接返回
if (existingRetriever != null) {
Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
if (result != null) {
return result;
}
// If result is null, the existing retriever is not fully populated yet by another thread.
// Proceed like caching wasn't possible for this current local attempt.
}
—————— getApplicationListeners start
org.springframework.context.event.AbstractApplicationEventMulticaster$CachedListenerRetriever
@Nullable
public volatile Set<ApplicationListener<?>> applicationListeners;
@Nullable
public volatile Set<String> applicationListenerBeans;
@Nullable
public Collection<ApplicationListener<?>> getApplicationListeners() {
Set<ApplicationListener<?>> applicationListeners = this.applicationListeners;
Set<String> applicationListenerBeans = this.applicationListenerBeans;
if (applicationListeners == null || applicationListenerBeans == null) {
// Not fully populated yet
return null;
}
List<ApplicationListener<?>> allListeners = new ArrayList<>(
applicationListeners.size() + applicationListenerBeans.size());
allListeners.addAll(applicationListeners);
if (!applicationListenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : applicationListenerBeans) {
try {
allListeners.add(beanFactory.getBean(listenerBeanName, ApplicationListener.class));
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
if (!applicationListenerBeans.isEmpty()) {
AnnotationAwareOrderComparator.sort(allListeners);
}
return allListeners;
}
创建监听器集合
List<ApplicationListener<?>> allListeners = new ArrayList<>(
applicationListeners.size() + applicationListenerBeans.size());
添加监听器实例
allListeners.addAll(applicationListeners);
监听器名称集合不为空时,遍历名称集合通过工厂实例获取监听器实例,添加至监听器实例集合
if (!applicationListenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : applicationListenerBeans) {
try {
allListeners.add(beanFactory.getBean(listenerBeanName, ApplicationListener.class));
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
监听器名称集合不为空时,将集合重新排序
if (!applicationListenerBeans.isEmpty()) {
AnnotationAwareOrderComparator.sort(allListeners);
}
—————— getApplicationListeners end
此时无已存在的检索器,继续执行
检索并返回监听器集合
return retrieveApplicationListeners(eventType, sourceType, newRetriever);
—————— retrieveApplicationListeners start
org.springframework.context.event.AbstractApplicationEventMulticaster
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);
Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.defaultRetriever) {
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
// Add programmatically registered listeners, including ones coming
// from ApplicationListenerDetector (singleton beans and inner beans).
for (ApplicationListener<?> listener : listeners) {
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
filteredListeners.add(listener);
}
allListeners.add(listener);
}
}
// Add listeners by bean name, potentially overlapping with programmatically
// registered listeners above - but here potentially with additional metadata.
if (!listenerBeans.isEmpty()) {
ConfigurableBeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
if (beanFactory.isSingleton(listenerBeanName)) {
filteredListeners.add(listener);
}
else {
filteredListenerBeans.add(listenerBeanName);
}
}
allListeners.add(listener);
}
}
else {
// Remove non-matching listeners that originally came from
// ApplicationListenerDetector, possibly ruled out by additional
// BeanDefinition metadata (e.g. factory method generics) above.
Object listener = beanFactory.getSingleton(listenerBeanName);
if (retriever != null) {
filteredListeners.remove(listener);
}
allListeners.remove(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null) {
if (filteredListenerBeans.isEmpty()) {
retriever.applicationListeners = new LinkedHashSet<>(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
}
else {
retriever.applicationListeners = filteredListeners;
retriever.applicationListenerBeans = filteredListenerBeans;
}
}
return allListeners;
}
创建所有监听器集合
List<ApplicationListener<?>> allListeners = new ArrayList<>();
创建过滤后的监听器集合
Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);
创建过滤后的监听器bean名称集合
Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);
声明监听器集合
Set<ApplicationListener<?>> listeners;
声明监听器bean名称集合
Set<String> listenerBeans;
将默认检索器的监听器集合及监听器bean名称集合作为初始值
synchronized (this.defaultRetriever) {
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
此处defaultRetriever
于之前实例化org.springframework.boot.context.event.EventPublishingRunListener
时,构造方法内赋值
遍历监听器集合,将支持事件的监听器加入集合
for (ApplicationListener<?> listener : listeners) {
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
filteredListeners.add(listener);
}
allListeners.add(listener);
}
}
——————— supportsEvent start
org.springframework.context.event.AbstractApplicationEventMulticaster
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
——————— supportsEvent end
supportsEvent
方法先根据监听器的类型将其转换为通用监听器或监听器代理,再调用统一的方法判断当前监听器是否同时支持指定的事件类型和源类型
判断监听器bean名称集合是否为空
if (!listenerBeans.isEmpty())
此时集合为空,后面再分析
监听器集合排序
AnnotationAwareOrderComparator.sort(allListeners);
若检索器不为空,设置检索器的监听器集合
if (retriever != null) {
if (filteredListenerBeans.isEmpty()) {
retriever.applicationListeners = new LinkedHashSet<>(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
}
else {
retriever.applicationListeners = filteredListeners;
retriever.applicationListenerBeans = filteredListenerBeans;
}
}
返回监听器集合
return allListeners;
总结retrieveApplicationListeners
方法
先筛选出符合给定事件类型和源类型的监听器
若指定检索器不为null,将这些监听器实例或bean名称赋值给指定检索器(作为缓存)
最后返回监听器实例集合
—————— retrieveApplicationListeners end
当前获取到符合的监听器共3个
org.springframework.boot.context.logging.LoggingApplicationListener
,
org.springframework.boot.autoconfigure.BackgroundPreinitializer
,
org.springframework.boot.context.config.DelegatingApplicationListener
————— getApplicationListeners end
遍历监听器集合
————— for start
调用当前监听器
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
—————— invokeListener start
org.springframework.context.event.SimpleApplicationEventMulticaster
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);
}
}
获取错误处理器
ErrorHandler errorHandler = getErrorHandler();
———————— getErrorHandler start
org.springframework.context.event.SimpleApplicationEventMulticaster
@Nullable
private ErrorHandler errorHandler;
@Nullable
protected ErrorHandler getErrorHandler() {
return this.errorHandler;
}
———————— getErrorHandler end
默认无错误处理器
执行监听器
doInvokeListener(listener, event);
——————— doInvokeListener start
org.springframework.context.event.SimpleApplicationEventMulticaster
@SuppressWarnings({"rawtypes", "unchecked"})
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()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
调用监听器的事件方法
listener.onApplicationEvent(event);
首先是org.springframework.boot.context.logging.LoggingApplicationListener
———————— onApplicationEvent start
org.springframework.boot.context.logging.LoggingApplicationListener
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
}
else if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
else if (event instanceof ContextClosedEvent
&& ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {
onContextClosedEvent();
}
else if (event instanceof ApplicationFailedEvent) {
onApplicationFailedEvent();
}
}
匹配启动事件类型
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
————————— onApplicationStartingEvent start
org.springframework.boot.context.logging.LoggingApplicationListener
private LoggingSystem loggingSystem;
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
this.loggingSystem.beforeInitialize();
}
获取日志系统实例
this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
—————————— get start
org.springframework.boot.logging.LoggingSystem
public static LoggingSystem get(ClassLoader classLoader) {
String loggingSystemClassName = System.getProperty(SYSTEM_PROPERTY);
if (StringUtils.hasLength(loggingSystemClassName)) {
if (NONE.equals(loggingSystemClassName)) {
return new NoOpLoggingSystem();
}
return get(classLoader, loggingSystemClassName);
}
LoggingSystem loggingSystem = SYSTEM_FACTORY.getLoggingSystem(classLoader);
Assert.state(loggingSystem != null, "No suitable logging system located");
return loggingSystem;
}
获取日志系统类名称
String loggingSystemClassName = System.getProperty(SYSTEM_PROPERTY);
org.springframework.boot.logging.LoggingSystem
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
即org.springframework.boot.logging.LoggingSystem
判断类名称是否为空
if (StringUtils.hasLength(loggingSystemClassName)) {
if (NONE.equals(loggingSystemClassName)) {
return new NoOpLoggingSystem();
}
return get(classLoader, loggingSystemClassName);
}
——————————— hasLength start
org.springframework.util.StringUtils
public static boolean hasLength(@Nullable String str) {
return (str != null && !str.isEmpty());
}
——————————— hasLength end
org.springframework.boot.logging.LoggingSystem
public static final String NONE = "none";
若类名为"none",创建并返回内部的无日志系统实例org.springframework.boot.logging.LoggingSystem$NoOpLoggingSystem
,即org.springframework.boot.logging.LoggingSystem
的空实现类
若类名不为空且不为"none",根据类名实例化并返回
——————————— get start
org.springframework.boot.logging.LoggingSystem
private static LoggingSystem get(ClassLoader classLoader, String loggingSystemClassName) {
try {
Class<?> systemClass = ClassUtils.forName(loggingSystemClassName, classLoader);
Constructor<?> constructor = systemClass.getDeclaredConstructor(ClassLoader.class);
constructor.setAccessible(true);
return (LoggingSystem) constructor.newInstance(classLoader);
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
——————————— get end
默认情况下类名为null,继续
通过系统工厂获取日志系统
LoggingSystem loggingSystem = SYSTEM_FACTORY.getLoggingSystem(classLoader);
org.springframework.boot.logging.LoggingSystem
private static final LoggingSystemFactory SYSTEM_FACTORY = LoggingSystemFactory.fromSpringFactories();
查看默认工厂实例
——————————— fromSpringFactories start
org.springframework.boot.logging.LoggingSystemFactory
static LoggingSystemFactory fromSpringFactories() {
return new DelegatingLoggingSystemFactory(
(classLoader) -> SpringFactoriesLoader.loadFactories(LoggingSystemFactory.class, classLoader));
}
———————————— DelegatingLoggingSystemFactory start
org.springframework.boot.logging.DelegatingLoggingSystemFactory
private final Function<ClassLoader, List<LoggingSystemFactory>> delegates;
DelegatingLoggingSystemFactory(Function<ClassLoader, List<LoggingSystemFactory>> delegates) {
this.delegates = delegates;
}
———————————— DelegatingLoggingSystemFactory end
得知org.springframework.boot.logging.DelegatingLoggingSystemFactory
为代理日志系统工厂,代理了获取日志系统工厂实例的方法
——————————— fromSpringFactories end
获取日志工厂实例
——————————— getLoggingSystem start
org.springframework.boot.logging.DelegatingLoggingSystemFactory
@Override
public LoggingSystem getLoggingSystem(ClassLoader classLoader) {
List<LoggingSystemFactory> delegates = (this.delegates != null) ? this.delegates.apply(classLoader) : null;
if (delegates != null) {
for (LoggingSystemFactory delegate : delegates) {
LoggingSystem loggingSystem = delegate.getLoggingSystem(classLoader);
if (loggingSystem != null) {
return loggingSystem;
}
}
}
return null;
}
获取日志工厂实例集合
List<LoggingSystemFactory> delegates = (this.delegates != null) ? this.delegates.apply(classLoader) : null;
即运行lambda
代码(classLoader) -> SpringFactoriesLoader.loadFactories(LoggingSystemFactory.class, classLoader)
———————————— loadFactories start
org.springframework.core.io.support.SpringFactoriesLoader
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryType, "'factoryType' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
List<T> result = new ArrayList<>(factoryImplementationNames.size());
for (String factoryImplementationName : factoryImplementationNames) {
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
AnnotationAwareOrderComparator.sort(result);
return result;
}
读取工厂实现类名称集合
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
创建工厂实例集合
List<T> result = new ArrayList<>(factoryImplementationNames.size());
遍历工厂实现类名称集合,实例化工厂并添加至集合
for (String factoryImplementationName : factoryImplementationNames) {
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
————————————— instantiateFactory start
org.springframework.core.io.support.SpringFactoriesLoader
@SuppressWarnings("unchecked")
private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
try {
Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
throw new IllegalArgumentException(
"Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
}
return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
}
catch (Throwable ex) {
throw new IllegalArgumentException(
"Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]",
ex);
}
}
获取可用构造器后传创建实例
return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance();
—————————————— accessibleConstructor start
org.springframework.util.ReflectionUtils
public static <T> Constructor<T> accessibleConstructor(Class<T> clazz, Class<?>... parameterTypes)
throws NoSuchMethodException {
Constructor<T> ctor = clazz.getDeclaredConstructor(parameterTypes);
makeAccessible(ctor);
return ctor;
}
获取构造器
Constructor<T> ctor = clazz.getDeclaredConstructor(parameterTypes);
这里获取为无参构造器
使构造器可用
makeAccessible(ctor);
——————————————— makeAccessible start
@SuppressWarnings("deprecation") // on JDK 9
public static void makeAccessible(Constructor<?> ctor) {
if ((!Modifier.isPublic(ctor.getModifiers()) ||
!Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) {
ctor.setAccessible(true);
}
}
——————————————— makeAccessible end
返回构造器
return ctor;
—————————————— accessibleConstructor end
————————————— instantiateFactory end
工厂实例集合排序
AnnotationAwareOrderComparator.sort(result);
返回工厂实例集合
return result;
———————————— loadFactories end
默认存在3个日志系统工厂实例
org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem$Factory
org.springframework.boot.logging.java.JavaLoggingSystem$Factory
获取第一个日志工厂的日志系统实例
if (delegates != null) {
for (LoggingSystemFactory delegate : delegates) {
LoggingSystem loggingSystem = delegate.getLoggingSystem(classLoader);
if (loggingSystem != null) {
return loggingSystem;
}
}
}
返回org.springframework.boot.logging.logback.LogbackLoggingSystem
实例
——————————— getLoggingSystem end
判断日志系统实例存在
Assert.state(loggingSystem != null, "No suitable logging system located");
返回日志系统实例
return loggingSystem;
—————————— get end
将日志系统实例进行预初始化操作
this.loggingSystem.beforeInitialize();
—————————— beforeInitialize start
org.springframework.boot.logging.logback.LogbackLoggingSystem
@Override
public void beforeInitialize() {
LoggerContext loggerContext = getLoggerContext();
if (isAlreadyInitialized(loggerContext)) {
return;
}
super.beforeInitialize();
loggerContext.getTurboFilterList().add(FILTER);
}
获取日志上下文
LoggerContext loggerContext = getLoggerContext();
——————————— getLoggerContext start
org.springframework.boot.logging.logback.LogbackLoggingSystem
private LoggerContext getLoggerContext() {
ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
Assert.isInstanceOf(LoggerContext.class, factory,
() -> String.format(
"LoggerFactory is not a Logback LoggerContext but Logback is on "
+ "the classpath. Either remove Logback or the competing "
+ "implementation (%s loaded from %s). If you are using "
+ "WebLogic you will need to add 'org.slf4j' to "
+ "prefer-application-packages in WEB-INF/weblogic.xml",
factory.getClass(), getLocation(factory)));
return (LoggerContext) factory;
}
获取日志工厂
ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
获取单例装订器
———————————— getSingleton start
org.slf4j.impl.StaticLoggerBinder
/**
* The unique instance of this class.
*/
private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
static {
SINGLETON.init();
}
public static StaticLoggerBinder getSingleton() {
return SINGLETON;
}
查看org.slf4j.impl.StaticLoggerBinder
构造方法
————————————— StaticLoggerBinder start
org.slf4j.impl.StaticLoggerBinder
private LoggerContext defaultLoggerContext = new LoggerContext();
private StaticLoggerBinder() {
defaultLoggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME);
}
查看ch.qos.logback.classic.LoggerContext
构造方法
—————————————— LoggerContext start
ch.qos.logback.classic.LoggerContext
final Logger root;
private int size;
private Map<String, Logger> loggerCache;
private LoggerContextVO loggerContextRemoteView;
private List<String> frameworkPackages;
public LoggerContext() {
super();
this.loggerCache = new ConcurrentHashMap<String, Logger>();
this.loggerContextRemoteView = new LoggerContextVO(this);
this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
this.root.setLevel(Level.DEBUG);
loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
initEvaluatorMap();
size = 1;
this.frameworkPackages = new ArrayList<String>();
}
父类构造方法
super();
——————————————— ContextBase start
ch.qos.logback.core.ContextBase
public ContextBase() {
initCollisionMaps();
}
初始化碰撞集合
———————————————— initCollisionMaps start
ch.qos.logback.core.ContextBase
protected void initCollisionMaps() {
putObject(FA_FILENAME_COLLISION_MAP, new HashMap<String, String>());
putObject(RFA_FILENAME_PATTERN_COLLISION_MAP, new HashMap<String, FileNamePattern>());
}
添加FileAppender
碰撞集合
putObject(FA_FILENAME_COLLISION_MAP, new HashMap<String, String>());
ch.qos.logback.core.CoreConstants
/**
* Key used to locate a collision map for FileAppender instances in context's object map.
*
* The collision map consists of enties of the type (appender name, File option)
*/
public static final String FA_FILENAME_COLLISION_MAP = "FA_FILENAME_COLLISION_MAP";
————————————————— putObject start
ch.qos.logback.core.ContextBase
Map<String, Object> objectMap = new HashMap<String, Object>();
public void putObject(String key, Object value) {
objectMap.put(key, value);
}
————————————————— putObject end
添加RollingFileAppender
碰撞集合
putObject(RFA_FILENAME_PATTERN_COLLISION_MAP, new HashMap<String, FileNamePattern>());
ch.qos.logback.core.CoreConstants
/**
* Key used to locate a collision map for RollingFileAppender instances in context's object map.
*
* The collision map consists of entities of the type (appender name, FileNamePattern option)
*/
public static final String RFA_FILENAME_PATTERN_COLLISION_MAP = "RFA_FILENAME_PATTERN_COLLISION_MAP";
———————————————— initCollisionMaps end
——————————————— ContextBase end
日志创建缓存
this.loggerCache = new ConcurrentHashMap<String, Logger>();
创建日志上下文远程视图
this.loggerContextRemoteView = new LoggerContextVO(this);
——————————————— LoggerContextVO start
ch.qos.logback.classic.spi.LoggerContextVO
final String name;
final Map<String, String> propertyMap;
final long birthTime;
public LoggerContextVO(LoggerContext lc) {
this.name = lc.getName();
this.propertyMap = lc.getCopyOfPropertyMap();
this.birthTime = lc.getBirthTime();
}
——————————————— LoggerContextVO end
旨在对外提供部分可视性
创建根日志
this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
org.slf4j.Logger
final public String ROOT_LOGGER_NAME = "ROOT";
——————————————— Logger start
ch.qos.logback.classic.Logger
/**
* The name of this logger
*/
private String name;
/**
* The parent of this category. All categories have at least one ancestor
* which is the root category.
*/
transient private Logger parent;
final transient LoggerContext loggerContext;
Logger(String name, Logger parent, LoggerContext loggerContext) {
this.name = name;
this.parent = parent;
this.loggerContext = loggerContext;
}
transient
关键字修饰的成员变量将不参与序列化
——————————————— Logger end
根日志命名为ROOT
设置根日志级别
this.root.setLevel(Level.DEBUG);
ch.qos.logback.classic.Level
public static final int DEBUG_INT = 10000;
/**
* The <code>DEBUG</code> level designates informational events of lower
* importance.
*/
public static final Level DEBUG = new Level(DEBUG_INT, "DEBUG");
——————————————— Level start
ch.qos.logback.classic.Level
public final int levelInt;
public final String levelStr;
private Level(int levelInt, String levelStr) {
this.levelInt = levelInt;
this.levelStr = levelStr;
}
——————————————— Level end
——————————————— setLevel start
ch.qos.logback.classic.Logger
public synchronized void setLevel(Level newLevel) {
if (level == newLevel) {
// nothing to do;
return;
}
if (newLevel == null && isRootLogger()) {
throw new IllegalArgumentException("The level of the root logger cannot be set to null");
}
level = newLevel;
if (newLevel == null) {
effectiveLevelInt = parent.effectiveLevelInt;
newLevel = parent.getEffectiveLevel();
} else {
effectiveLevelInt = newLevel.levelInt;
}
if (childrenList != null) {
int len = childrenList.size();
for (int i = 0; i < len; i++) {
Logger child = (Logger) childrenList.get(i);
// tell child to handle parent levelInt change
child.handleParentLevelChange(effectiveLevelInt);
}
}
// inform listeners
loggerContext.fireOnLevelChange(this, newLevel);
}
对比新旧等级
if (level == newLevel) {
// nothing to do;
return;
}
判断新等级是否符合
if (newLevel == null && isRootLogger()) {
throw new IllegalArgumentException("The level of the root logger cannot be set to null");
}
———————————————— isRootLogger start
ch.qos.logback.classic.Logger
private boolean isRootLogger() {
// only the root logger has a null parent
return parent == null;
}
仅根日志父日志为null
———————————————— isRootLogger end
即根日志等级不可为空
获取有效的等级数值
level = newLevel;
if (newLevel == null) {
effectiveLevelInt = parent.effectiveLevelInt;
newLevel = parent.getEffectiveLevel();
} else {
effectiveLevelInt = newLevel.levelInt;
}
未指定等级时,使用父日志的等级数值
遍历子日志集合,使其处理等级变化
ch.qos.logback.classic.Logger
if (childrenList != null) {
int len = childrenList.size();
for (int i = 0; i < len; i++) {
Logger child = (Logger) childrenList.get(i);
// tell child to handle parent levelInt change
child.handleParentLevelChange(effectiveLevelInt);
}
}
———————————————— handleParentLevelChange start
ch.qos.logback.classic.Logger
private synchronized void handleParentLevelChange(int newParentLevelInt) {
// changes in the parent levelInt affect children only if their levelInt is
// null
if (level == null) {
effectiveLevelInt = newParentLevelInt;
// propagate the parent levelInt change to this logger's children
if (childrenList != null) {
int len = childrenList.size();
for (int i = 0; i < len; i++) {
Logger child = (Logger) childrenList.get(i);
child.handleParentLevelChange(newParentLevelInt);
}
}
}
}
递归调用子日志处理等级变化
———————————————— handleParentLevelChange end
通知等级变化
loggerContext.fireOnLevelChange(this, newLevel);
———————————————— fireOnLevelChange start
ch.qos.logback.classic.LoggerContext
final private List<LoggerContextListener> loggerContextListenerList = new ArrayList<LoggerContextListener>();
void fireOnLevelChange(Logger logger, Level level) {
for (LoggerContextListener listener : loggerContextListenerList) {
listener.onLevelChange(logger, level);
}
}
当前为设置过日志上下文监听器,loggerContextListenerList
为空
———————————————— fireOnLevelChange end
——————————————— setLevel end
将根日志设置为DEBUG级别
添加根日志缓存
loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
初始化评估集合
initEvaluatorMap();
——————————————— initEvaluatorMap start
ch.qos.logback.classic.LoggerContext
void initEvaluatorMap() {
putObject(EVALUATOR_MAP, new HashMap<String, EventEvaluator<?>>());
}
ch.qos.logback.core.CoreConstants
/**
* The key used in locating the evaluator map in context's object map.
*/
public static final String EVALUATOR_MAP = "EVALUATOR_MAP";
——————————————— initEvaluatorMap end
设置大小
size = 1;
创建框架包集合
this.frameworkPackages = new ArrayList<String>();
—————————————— LoggerContext end
设置默认日志上下文名称
ch.qos.logback.core.CoreConstants
public static final String DEFAULT_CONTEXT_NAME = "default";
—————————————— setName start
ch.qos.logback.classic.LoggerContext
@Override
public void setName(String name) {
super.setName(name);
updateLoggerContextVO();
}
使用父级方法设置名称
super.setName(name);
——————————————— setName start
ch.qos.logback.core.ContextBase
public void setName(String name) throws IllegalStateException {
if (name != null && name.equals(this.name)) {
return; // idempotent naming
}
if (this.name == null || CoreConstants.DEFAULT_CONTEXT_NAME.equals(this.name)) {
this.name = name;
} else {
throw new IllegalStateException("Context has been already given a name");
}
}
仅名称不存在或为默认名称default时可设置
——————————————— setName end
更新日志上下文视图
updateLoggerContextVO();
——————————————— updateLoggerContextVO start
ch.qos.logback.classic.LoggerContext
private void updateLoggerContextVO() {
loggerContextRemoteView = new LoggerContextVO(this);
}
——————————————— updateLoggerContextVO end
—————————————— setName end
————————————— StaticLoggerBinder end
初始化
————————————— init start
org.slf4j.impl.StaticLoggerBinder
void init() {
try {
try {
new ContextInitializer(defaultLoggerContext).autoConfig();
} catch (JoranException je) {
Util.report("Failed to auto configure default logger context", je);
}
// logback-292
if (!StatusUtil.contextHasStatusListener(defaultLoggerContext)) {
StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);
}
contextSelectorBinder.init(defaultLoggerContext, KEY);
initialized = true;
} catch (Exception t) { // see LOGBACK-1159
Util.report("Failed to instantiate [" + LoggerContext.class.getName() + "]", t);
}
}
创建上下文初始化器并自动配置
new ContextInitializer(defaultLoggerContext).autoConfig();
查看构造方法
—————————————— ContextInitializer start
ch.qos.logback.classic.util.ContextInitializer
final LoggerContext loggerContext;
public ContextInitializer(LoggerContext loggerContext) {
this.loggerContext = loggerContext;
}
—————————————— ContextInitializer end
自动配置
—————————————— autoConfig start
ch.qos.logback.classic.util.ContextInitializer
public void autoConfig() throws JoranException {
StatusListenerConfigHelper.installIfAsked(loggerContext);
URL url = findURLOfDefaultConfigurationFile(true);
if (url != null) {
configureByResource(url);
} else {
Configurator c = EnvUtil.loadFromServiceLoader(Configurator.class);
if (c != null) {
try {
c.setContext(loggerContext);
c.configure(loggerContext);
} catch (Exception e) {
throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader", c != null ? c.getClass()
.getCanonicalName() : "null"), e);
}
} else {
BasicConfigurator basicConfigurator = new BasicConfigurator();
basicConfigurator.setContext(loggerContext);
basicConfigurator.configure(loggerContext);
}
}
}
设置状态监听器
StatusListenerConfigHelper.installIfAsked(loggerContext);
——————————————— installIfAsked start
ch.qos.logback.core.util.StatusListenerConfigHelper
public static void installIfAsked(Context context) {
String slClass = OptionHelper.getSystemProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY);
if (!OptionHelper.isEmpty(slClass)) {
addStatusListener(context, slClass);
}
}
从系统属性获取状态监听器名称
String slClass = OptionHelper.getSystemProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY);
ch.qos.logback.core.CoreConstants
final public static String STATUS_LISTENER_CLASS_KEY = "logback.statusListenerClass";
———————————————— getSystemProperty start
ch.qos.logback.core.util.OptionHelper
public static String getSystemProperty(String key) {
try {
return System.getProperty(key);
} catch (SecurityException e) {
return null;
}
}
———————————————— getSystemProperty end
默认无监听器配置,即logback.statusListenerClass
配置为null
——————————————— installIfAsked end
查找默认配置文件路径
URL url = findURLOfDefaultConfigurationFile(true);
——————————————— findURLOfDefaultConfigurationFile start
ch.qos.logback.classic.util.ContextInitializer
public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {
ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);
URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
if (url != null) {
return url;
}
url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
if (url != null) {
return url;
}
return getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus);
}
获取当前实例的类加载器
ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);
———————————————— getClassLoaderOfObject start
ch.qos.logback.core.util.Loader
public static ClassLoader getClassLoaderOfObject(Object o) {
if (o == null) {
throw new NullPointerException("Argument cannot be null");
}
return getClassLoaderOfClass(o.getClass());
}
————————————————— getClassLoaderOfClass start
ch.qos.logback.core.util.Loader
public static ClassLoader getClassLoaderOfClass(final Class<?> clazz) {
ClassLoader cl = clazz.getClassLoader();
if (cl == null) {
return ClassLoader.getSystemClassLoader();
} else {
return cl;
}
}
————————————————— getClassLoaderOfClass end
———————————————— getClassLoaderOfObject end
从系统属性查找配置文件地址
URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
———————————————— findConfigFileURLFromSystemProperties start
ch.qos.logback.classic.util.ContextInitializer
private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) {
String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY);
if (logbackConfigFile != null) {
URL result = null;
try {
result = new URL(logbackConfigFile);
return result;
} catch (MalformedURLException e) {
// so, resource is not a URL:
// attempt to get the resource from the class path
result = Loader.getResource(logbackConfigFile, classLoader);
if (result != null) {
return result;
}
File f = new File(logbackConfigFile);
if (f.exists() && f.isFile()) {
try {
result = f.toURI().toURL();
return result;
} catch (MalformedURLException e1) {
}
}
} finally {
if (updateStatus) {
statusOnResourceSearch(logbackConfigFile, classLoader, result);
}
}
}
return null;
}
从系统属性获取配置文件值
String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY);
ch.qos.logback.classic.util.ContextInitializer
final public static String CONFIG_FILE_PROPERTY = "logback.configurationFile";
默认logback.configurationFile
未配置,返回null
若值不为null,则将值按如下顺序逐一尝试
- 完整的资源地址
result = new URL(logbackConfigFile);
return result;
- 类路径相对资源地址
result = Loader.getResource(logbackConfigFile, classLoader);
if (result != null) {
return result;
}
————————————————— getResource start
ch.qos.logback.core.util.Loader
public static URL getResource(String resource, ClassLoader classLoader) {
try {
return classLoader.getResource(resource);
} catch (Throwable t) {
return null;
}
}
————————————————— getResource end
3. 文件路径
File f = new File(logbackConfigFile);
if (f.exists() && f.isFile()) {
try {
result = f.toURI().toURL();
return result;
} catch (MalformedURLException e1) {
}
}
记录资源搜索状态
if (updateStatus) {
statusOnResourceSearch(logbackConfigFile, classLoader, result);
}
————————————————— statusOnResourceSearch start
ch.qos.logback.classic.util.ContextInitializer
private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) {
StatusManager sm = loggerContext.getStatusManager();
if (url == null) {
sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]", loggerContext));
} else {
sm.add(new InfoStatus("Found resource [" + resourceName + "] at [" + url.toString() + "]", loggerContext));
multiplicityWarning(resourceName, classLoader);
}
}
获取状态管理器
StatusManager sm = loggerContext.getStatusManager();
—————————————————— getStatusManager start
ch.qos.logback.core.ContextBase
private StatusManager sm = new BasicStatusManager();
public StatusManager getStatusManager() {
return sm;
}
—————————————————— getStatusManager end
创建状态实例并添加
sm.add(new InfoStatus("Found resource [" + resourceName + "] at [" + url.toString() + "]", loggerContext));
查看状态构造方法
—————————————————— InfoStatus start
ch.qos.logback.core.status.InfoStatus
public InfoStatus(String msg, Object origin) {
super(Status.INFO, msg, origin);
}
ch.qos.logback.core.status.Status
int INFO = 0;
查看父类构造方法
ch.qos.logback.core.status.StatusBase
int level;
final String message;
final Object origin;
Throwable throwable;
long date;
StatusBase(int level, String msg, Object origin) {
this(level, msg, origin, null);
}
StatusBase(int level, String msg, Object origin, Throwable t) {
this.level = level;
this.message = msg;
this.origin = origin;
this.throwable = t;
this.date = System.currentTimeMillis();
}
—————————————————— InfoStatus end
添加至状态管理器
—————————————————— add start
ch.qos.logback.core.BasicStatusManager
public static final int MAX_HEADER_COUNT = 150;
public static final int TAIL_SIZE = 150;
int count = 0;
final protected List<Status> statusList = new ArrayList<Status>();
final protected CyclicBuffer<Status> tailBuffer = new CyclicBuffer<Status>(TAIL_SIZE);
final protected LogbackLock statusListLock = new LogbackLock();
int level = Status.INFO;
public void add(Status newStatus) {
// LBCORE-72: fire event before the count check
fireStatusAddEvent(newStatus);
count++;
if (newStatus.getLevel() > level) {
level = newStatus.getLevel();
}
synchronized (statusListLock) {
if (statusList.size() < MAX_HEADER_COUNT) {
statusList.add(newStatus);
} else {
tailBuffer.add(newStatus);
}
}
}
触发状态添加事件
fireStatusAddEvent(newStatus);
——————————————————— fireStatusAddEvent start
ch.qos.logback.core.BasicStatusManager
final protected List<StatusListener> statusListenerList = new ArrayList<StatusListener>();
final protected LogbackLock statusListenerListLock = new LogbackLock();
private void fireStatusAddEvent(Status status) {
synchronized (statusListenerListLock) {
for (StatusListener sl : statusListenerList) {
sl.addStatusEvent(status);
}
}
}
遍历状态监听器集合并添加状态事件
——————————————————— fireStatusAddEvent end
当前监听器集合为空
计数增加
count++;
更新最大状态等级
if (newStatus.getLevel() > level) {
level = newStatus.getLevel();
}
添加状态实例
if (statusList.size() < MAX_HEADER_COUNT) {
statusList.add(newStatus);
} else {
tailBuffer.add(newStatus);
}
若状态集合长度小于最大头部计数,将状态实例添加至集合
否则将状态实例添加至尾部缓冲区
—————————————————— add end
多重警告
multiplicityWarning(resourceName, classLoader);
—————————————————— multiplicityWarning start
ch.qos.logback.classic.util.ContextInitializer
private void multiplicityWarning(String resourceName, ClassLoader classLoader) {
Set<URL> urlSet = null;
StatusManager sm = loggerContext.getStatusManager();
try {
urlSet = Loader.getResources(resourceName, classLoader);
} catch (IOException e) {
sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]", loggerContext, e));
}
if (urlSet != null && urlSet.size() > 1) {
sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.", loggerContext));
for (URL url : urlSet) {
sm.add(new WarnStatus("Resource [" + resourceName + "] occurs at [" + url.toString() + "]", loggerContext));
}
}
}
若指定资源存在多个,则添加告警状态
—————————————————— multiplicityWarning end
————————————————— statusOnResourceSearch end
———————————————— findConfigFileURLFromSystemProperties end
若未发现配置,则继续
从类加载路径查找配置文件
url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
ch.qos.logback.classic.util.ContextInitializer
final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml";
查找logback-test.xml
文件
———————————————— getResource start
ch.qos.logback.classic.util.ContextInitializer
private URL getResource(String filename, ClassLoader myClassLoader, boolean updateStatus) {
URL url = Loader.getResource(filename, myClassLoader);
if (updateStatus) {
statusOnResourceSearch(filename, myClassLoader, url);
}
return url;
}
———————————————— getResource end
若未发现配置,则继续
从类加载路径查找配置文件java
return getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus);
ch.qos.logback.classic.util.ContextInitializer
final public static String AUTOCONFIG_FILE = "logback.xml";
查找logback.xml
文件
——————————————— findURLOfDefaultConfigurationFile end
若存在配置
configureByResource(url);
——————————————— configureByResource start
ch.qos.logback.classic.util.ContextInitializer
public void configureByResource(URL url) throws JoranException {
if (url == null) {
throw new IllegalArgumentException("URL argument cannot be null");
}
final String urlString = url.toString();
if (urlString.endsWith("xml")) {
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(loggerContext);
configurator.doConfigure(url);
} else {
throw new LogbackException("Unexpected filename extension of file [" + url.toString() + "]. Should be .xml");
}
}
创建ch.qos.logback.classic.joran.JoranConfigurator
实例并进行配置
——————————————— configureByResource end
若无配置文件,读取或创建配置器并配置
先尝试读取配置器
Configurator c = EnvUtil.loadFromServiceLoader(Configurator.class);
——————————————— loadFromServiceLoader start
ch.qos.logback.classic.util.EnvUtil
public static <T> T loadFromServiceLoader(Class<T> c) {
ServiceLoader<T> loader = ServiceLoader.load(c, getServiceLoaderClassLoader());
Iterator<T> it = loader.iterator();
if (it.hasNext())
return it.next();
return null;
}
即通过SPI机制获取第一个实现类
——————————————— loadFromServiceLoader end
默认无配置
未找到实现类,则创建配置器
BasicConfigurator basicConfigurator = new BasicConfigurator();
设置上下文
basicConfigurator.setContext(loggerContext);
——————————————— setContext start
ch.qos.logback.core.spi.ContextAwareBase
protected Context context;
public void setContext(Context context) {
if (this.context == null) {
this.context = context;
} else if (this.context != context) {
throw new IllegalStateException("Context has been already set");
}
}
仅可设置一次
——————————————— setContext end
进行配置
basicConfigurator.configure(loggerContext);
——————————————— configure start
ch.qos.logback.classic.BasicConfigurator
public void configure(LoggerContext lc) {
addInfo("Setting up default configuration.");
ConsoleAppender<ILoggingEvent> ca = new ConsoleAppender<ILoggingEvent>();
ca.setContext(lc);
ca.setName("console");
LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<ILoggingEvent>();
encoder.setContext(lc);
// same as
// PatternLayout layout = new PatternLayout();
// layout.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
TTLLLayout layout = new TTLLLayout();
layout.setContext(lc);
layout.start();
encoder.setLayout(layout);
ca.setEncoder(encoder);
ca.start();
Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.addAppender(ca);
}
添加信息状态
addInfo("Setting up default configuration.");
———————————————— addInfo start
ch.qos.logback.core.spi.ContextAwareBase
public void addInfo(String msg) {
addStatus(new InfoStatus(msg, getDeclaredOrigin()));
}
getDeclaredOrigin()
方法获取原始上下文实例
————————————————— getDeclaredOrigin start
ch.qos.logback.core.spi.ContextAwareBase
final Object declaredOrigin;
protected Object getDeclaredOrigin() {
return declaredOrigin;
}
查看无参构造方法
—————————————————— ContextAwareBase start
ch.qos.logback.core.spi.ContextAwareBase
final Object declaredOrigin;
public ContextAwareBase() {
declaredOrigin = this;
}
默认为自身
—————————————————— ContextAwareBase end
————————————————— getDeclaredOrigin end
可知此处获取的实例即为前面创建的ch.qos.logback.classic.BasicConfigurator
添加状态
————————————————— addStatus start
ch.qos.logback.core.spi.ContextAwareBase
public void addStatus(Status status) {
if (context == null) {
if (noContextWarning++ == 0) {
System.out.println("LOGBACK: No context given for " + this);
}
return;
}
StatusManager sm = context.getStatusManager();
if (sm != null) {
sm.add(status);
}
}
————————————————— addStatus end
———————————————— addInfo end
创建控制台附加器
ConsoleAppender<ILoggingEvent> ca = new ConsoleAppender<ILoggingEvent>();
ca.setContext(lc);
ca.setName("console");
创建布局编码器及布局实例并设置
LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<ILoggingEvent>();
encoder.setContext(lc);
// same as
// PatternLayout layout = new PatternLayout();
// layout.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
TTLLLayout layout = new TTLLLayout();
layout.setContext(lc);
layout.start();
encoder.setLayout(layout);
为控制台附加器设置编码器并启动
ca.setEncoder(encoder);
ca.start();
将控制台附加器添加至根日志实例
Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.addAppender(ca);
——————————————— configure end
—————————————— autoConfig end
判断日志上下文是否有状态监听器
StatusUtil.contextHasStatusListener(defaultLoggerContext)
—————————————— contextHasStatusListener start
ch.qos.logback.core.status.StatusUtil
static public boolean contextHasStatusListener(Context context) {
StatusManager sm = context.getStatusManager();
if (sm == null)
return false;
List<StatusListener> listeners = sm.getCopyOfStatusListenerList();
if (listeners == null || listeners.size() == 0)
return false;
else
return true;
}
—————————————— contextHasStatusListener end
前面已知状态监听器集合为空
打印错误或警告信息
StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);
—————————————— printInCaseOfErrorsOrWarnings start
ch.qos.logback.core.util.StatusPrinter
public static void printInCaseOfErrorsOrWarnings(Context context) {
printInCaseOfErrorsOrWarnings(context, 0);
}
public static void printInCaseOfErrorsOrWarnings(Context context, long threshold) {
if (context == null) {
throw new IllegalArgumentException("Context argument cannot be null");
}
StatusManager sm = context.getStatusManager();
if (sm == null) {
ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager");
} else {
StatusUtil statusUtil = new StatusUtil(context);
if (statusUtil.getHighestLevel(threshold) >= ErrorStatus.WARN) {
print(sm, threshold);
}
}
}
创建状态工具
StatusUtil statusUtil = new StatusUtil(context);
——————————————— StatusUtil start
ch.qos.logback.core.status.StatusUtil
StatusManager sm;
public StatusUtil(Context context) {
this.sm = context.getStatusManager();
}
——————————————— StatusUtil end
获取最高级别
statusUtil.getHighestLevel(threshold)
——————————————— getHighestLevel start
ch.qos.logback.core.status.StatusUtil
public int getHighestLevel(long threshold) {
List<Status> filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold);
int maxLevel = Status.INFO;
for (Status s : filteredList) {
if (s.getLevel() > maxLevel)
maxLevel = s.getLevel();
}
return maxLevel;
}
根据时间阈值过滤状态集合
List<Status> filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold);
———————————————— filterStatusListByTimeThreshold start
ch.qos.logback.core.status.StatusUtil
static public List<Status> filterStatusListByTimeThreshold(List<Status> rawList, long threshold) {
List<Status> filteredList = new ArrayList<Status>();
for (Status s : rawList) {
if (s.getDate() >= threshold)
filteredList.add(s);
}
return filteredList;
}
可知threshold
为状态时间戳阈值,0即全部状态
———————————————— filterStatusListByTimeThreshold end
——————————————— getHighestLevel end
最终返回高于INFO的最高级别
当最高级别大于或等于WARN时,打印状态
print(sm, threshold);
——————————————— print start
ch.qos.logback.core.util.StatusPrinter
public static void print(StatusManager sm, long threshold) {
StringBuilder sb = new StringBuilder();
List<Status> filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold);
buildStrFromStatusList(sb, filteredList);
ps.println(sb.toString());
}
构建状态集合字符串
buildStrFromStatusList(sb, filteredList);
打印
ps.println(sb.toString());
ch.qos.logback.core.util.StatusPrinter
private static PrintStream ps = System.out;
即控制台输出
——————————————— print end
—————————————— printInCaseOfErrorsOrWarnings end
初始化上下文选择器装订器
contextSelectorBinder.init(defaultLoggerContext, KEY);
先看defaultLoggerContext
org.slf4j.impl.StaticLoggerBinder
private final ContextSelectorStaticBinder contextSelectorBinder = ContextSelectorStaticBinder.getSingleton();
—————————————— ContextSelectorStaticBinder start
ch.qos.logback.classic.util.ContextSelectorStaticBinder
static ContextSelectorStaticBinder singleton = new ContextSelectorStaticBinder();
public static ContextSelectorStaticBinder getSingleton() {
return singleton;
}
—————————————— ContextSelectorStaticBinder end
接着看KEY
org.slf4j.impl.StaticLoggerBinder
private static Object KEY = new Object();
初始化
—————————————— init start
ch.qos.logback.classic.util.ContextSelectorStaticBinder
public void init(LoggerContext defaultLoggerContext, Object key) throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException {
if (this.key == null) {
this.key = key;
} else if (this.key != key) {
throw new IllegalAccessException("Only certain classes can access this method.");
}
String contextSelectorStr = OptionHelper.getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR);
if (contextSelectorStr == null) {
contextSelector = new DefaultContextSelector(defaultLoggerContext);
} else if (contextSelectorStr.equals("JNDI")) {
// if jndi is specified, let's use the appropriate class
contextSelector = new ContextJNDISelector(defaultLoggerContext);
} else {
contextSelector = dynamicalContextSelector(defaultLoggerContext, contextSelectorStr);
}
}
从系统属性中获取配置的值
String contextSelectorStr = OptionHelper.getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR);
ch.qos.logback.classic.ClassicConstants
public static final String LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector";
根据获取的值创建上下文选择器
- 值为null,
ch.qos.logback.classic.selector.DefaultContextSelector
,默认上下文选择器 - 值为JNDI,
ch.qos.logback.classic.selector.ContextJNDISelector
- 值可能为类名,动态创建实例
——————————————— dynamicalContextSelector start
ch.qos.logback.classic.util.ContextSelectorStaticBinder
static ContextSelector dynamicalContextSelector(LoggerContext defaultLoggerContext, String contextSelectorStr) throws ClassNotFoundException,
SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException,
InvocationTargetException {
Class<?> contextSelectorClass = Loader.loadClass(contextSelectorStr);
Constructor cons = contextSelectorClass.getConstructor(new Class[] { LoggerContext.class });
return (ContextSelector) cons.newInstance(defaultLoggerContext);
}
——————————————— dynamicalContextSelector end
—————————————— init end
初始化完成
initialized = true;
————————————— init end
———————————— getSingleton end
接着获取其日志工厂实例
———————————— getLoggerFactory start
org.slf4j.impl.StaticLoggerBinder
public ILoggerFactory getLoggerFactory() {
if (!initialized) {
return defaultLoggerContext;
}
if (contextSelectorBinder.getContextSelector() == null) {
throw new IllegalStateException("contextSelector cannot be null. See also " + NULL_CS_URL);
}
return contextSelectorBinder.getContextSelector().getLoggerContext();
}
此时已完成初始化
返回日志上下文
return contextSelectorBinder.getContextSelector().getLoggerContext();
获取上下文选择器
————————————— getContextSelector start
ch.qos.logback.classic.util.ContextSelectorStaticBinder
public ContextSelector getContextSelector() {
return contextSelector;
}
————————————— getContextSelector end
通过选择器获取上下文
————————————— getLoggerContext start
ch.qos.logback.classic.selector.DefaultContextSelector
public LoggerContext getLoggerContext() {
return getDefaultLoggerContext();
}
—————————————— getDefaultLoggerContext start
ch.qos.logback.classic.selector.DefaultContextSelector
public LoggerContext getDefaultLoggerContext() {
return defaultLoggerContext;
}
—————————————— getDefaultLoggerContext end
获取到前面名为default的默认日志上下文
————————————— getLoggerContext end
———————————— getLoggerFactory end
判断实例是否属于ch.qos.logback.classic.LoggerContext
Assert.isInstanceOf(LoggerContext.class, factory,
() -> String.format(
"LoggerFactory is not a Logback LoggerContext but Logback is on "
+ "the classpath. Either remove Logback or the competing "
+ "implementation (%s loaded from %s). If you are using "
+ "WebLogic you will need to add 'org.slf4j' to "
+ "prefer-application-packages in WEB-INF/weblogic.xml",
factory.getClass(), getLocation(factory)));
转换实例类型并返回
return (LoggerContext) factory;
——————————— getLoggerContext end
判断日志上下文实例是否初始化完成
if (isAlreadyInitialized(loggerContext)) {
return;
}
——————————— isAlreadyInitialized start
org.springframework.boot.logging.logback.LogbackLoggingSystem
private boolean isAlreadyInitialized(LoggerContext loggerContext) {
return loggerContext.getObject(LoggingSystem.class.getName()) != null;
}
———————————— getObject start
ch.qos.logback.core.ContextBase
Map<String, Object> objectMap = new HashMap<String, Object>();
public Object getObject(String key) {
return objectMap.get(key);
}
———————————— getObject end
此时尚未初始化,objectMap
中无键org.springframework.boot.logging.LoggingSystem
——————————— isAlreadyInitialized end
父类预初始化
super.beforeInitialize();
——————————— beforeInitialize end
org.springframework.boot.logging.Slf4JLoggingSystem
@Override
public void beforeInitialize() {
super.beforeInitialize();
configureJdkLoggingBridgeHandler();
}
父类预初始化
super.beforeInitialize();
———————————— beforeInitialize start
org.springframework.boot.logging.AbstractLoggingSystem
@Override
public void beforeInitialize() {
}
———————————— beforeInitialize end
父类方法为空
配置jdk日志桥接处理器
configureJdkLoggingBridgeHandler();
———————————— configureJdkLoggingBridgeHandler start
org.springframework.boot.logging.Slf4JLoggingSystem
private void configureJdkLoggingBridgeHandler() {
try {
if (isBridgeJulIntoSlf4j()) {
removeJdkLoggingBridgeHandler();
SLF4JBridgeHandler.install();
}
}
catch (Throwable ex) {
// Ignore. No java.util.logging bridge is installed.
}
}
判断是否将JUL
桥接至SLF4J
if (isBridgeJulIntoSlf4j())
————————————— isBridgeJulIntoSlf4j start
org.springframework.boot.logging.Slf4JLoggingSystem
protected final boolean isBridgeJulIntoSlf4j() {
return isBridgeHandlerAvailable() && isJulUsingASingleConsoleHandlerAtMost();
}
判断桥接处理器是否可用
isBridgeHandlerAvailable()
—————————————— isBridgeHandlerAvailable start
org.springframework.boot.logging.Slf4JLoggingSystem
private static final String BRIDGE_HANDLER = "org.slf4j.bridge.SLF4JBridgeHandler";
protected final boolean isBridgeHandlerAvailable() {
return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
}
—————————————— isBridgeHandlerAvailable end
即是否存在org.slf4j.bridge.SLF4JBridgeHandler
类
判断JUL
是否至多使用一个控制台处理器
isJulUsingASingleConsoleHandlerAtMost()
—————————————— isJulUsingASingleConsoleHandlerAtMost start
org.springframework.boot.logging.Slf4JLoggingSystem
private boolean isJulUsingASingleConsoleHandlerAtMost() {
Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
return handlers.length == 0 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler);
}
获取根日志实例
Logger rootLogger = LogManager.getLogManager().getLogger("");
获取处理器
Handler[] handlers = rootLogger.getHandlers();
判断处理器是否仅为一个且为java.util.logging.ConsoleHandler
或其子实例
return handlers.length == 0 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler);
—————————————— isJulUsingASingleConsoleHandlerAtMost end
————————————— isBridgeJulIntoSlf4j end
以上条件均满足,继续
移除jdk
日志桥接处理器
removeJdkLoggingBridgeHandler();
————————————— removeJdkLoggingBridgeHandler start
org.springframework.boot.logging.Slf4JLoggingSystem
private void removeJdkLoggingBridgeHandler() {
try {
removeDefaultRootHandler();
SLF4JBridgeHandler.uninstall();
}
catch (Throwable ex) {
// Ignore and continue
}
}
移除默认的根处理器
removeDefaultRootHandler();
—————————————— removeDefaultRootHandler start
org.springframework.boot.logging.Slf4JLoggingSystem
private void removeDefaultRootHandler() {
try {
Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
if (handlers.length == 1 && handlers[0] instanceof ConsoleHandler) {
rootLogger.removeHandler(handlers[0]);
}
}
catch (Throwable ex) {
// Ignore and continue
}
}
—————————————— removeDefaultRootHandler end
卸载SLF4J
桥接处理器
SLF4JBridgeHandler.uninstall();
—————————————— uninstall start
org.slf4j.bridge.SLF4JBridgeHandler
public static void uninstall() throws SecurityException {
java.util.logging.Logger rootLogger = getRootLogger();
Handler[] handlers = rootLogger.getHandlers();
for (int i = 0; i < handlers.length; i++) {
if (handlers[i] instanceof SLF4JBridgeHandler) {
rootLogger.removeHandler(handlers[i]);
}
}
}
—————————————— uninstall end
————————————— removeJdkLoggingBridgeHandler end
安装SLF4J
桥接处理器
SLF4JBridgeHandler.install();
org.slf4j.bridge.SLF4JBridgeHandler
public static void install() {
LogManager.getLogManager().getLogger("").addHandler(new SLF4JBridgeHandler());
}
———————————— configureJdkLoggingBridgeHandler end
——————————— beforeInitialize end
至此,org.springframework.boot.logging.Slf4JLoggingSystem
预初始化完成
在日志上下文实例中加入过滤器
loggerContext.getTurboFilterList().add(FILTER);
org.springframework.boot.logging.Slf4JLoggingSystem
private static final TurboFilter FILTER = new TurboFilter() {
@Override
public FilterReply decide(Marker marker, ch.qos.logback.classic.Logger logger, Level level, String format,
Object[] params, Throwable t) {
return FilterReply.DENY;
}
};
ch.qos.logback.classic.turbo.TurboFilter
定义了public abstract FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t);
抽象方法,通过返回值决定是否对日志过滤
FILTER
的decide
方法始终返回ch.qos.logback.core.spi.FilterReply.DENY
这将过滤掉所有的日志输出
——————————— getTurboFilterList start
ch.qos.logback.classic.LoggerContext
private final TurboFilterList turboFilterList = new TurboFilterList();
public TurboFilterList getTurboFilterList() {
return turboFilterList;
}
——————————— getTurboFilterList end
ch.qos.logback.classic.spi.TurboFilterList
继承自java.util.concurrent.CopyOnWriteArrayList
—————————— beforeInitialize end
————————— onApplicationStartingEvent end
———————— onApplicationEvent end
至此org.springframework.boot.context.logging.LoggingApplicationListener
监听器完成了对org.springframework.boot.context.event.ApplicationStartingEvent
事件的处理
接着是org.springframework.boot.autoconfigure.BackgroundPreinitializer
———————— onApplicationEvent start
org.springframework.boot.autoconfigure.BackgroundPreinitializer
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
if (!ENABLED) {
return;
}
if (event instanceof ApplicationEnvironmentPreparedEvent
&& preinitializationStarted.compareAndSet(false, true)) {
performPreinitialization();
}
if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)
&& preinitializationStarted.get()) {
try {
preinitializationComplete.await();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
———————— onApplicationEvent end
未匹配当前事件类型ApplicationStartingEvent
,跳过
最后是org.springframework.boot.context.config.DelegatingApplicationListener
———————— onApplicationEvent start
org.springframework.boot.context.config.DelegatingApplicationListener
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<ApplicationEvent> listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
if (this.multicaster != null) {
this.multicaster.multicastEvent(event);
}
}
———————— onApplicationEvent end
同样未匹配当前事件类型ApplicationStartingEvent
,跳过
——————— doInvokeListener end
—————— invokeListener end
————— for end
———— multicastEvent end
——— starting end
步骤处理
if (stepAction != null) {
stepAction.accept(step);
}
步骤结束
step.end();
—— doWithListeners end
— starting end