Springboot 源码分析环境搭建部分
step 1:下载源码 spring.io 选择 springboot 点击github下载1.5.x源码
step 2 : 配置jdk 1.8 、maven
step 3: mvn clean install -DskipTests -Pfast //跳过测试用例
SpringApplication初始化、启动
org.springframework.boot.SpringApplication#SpringApplication(java.lang.Object…) 这个类就是SpringApplication的构造方法。初始化工作
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
* @param sources the bean sources
* @see #run(Object, String[])
* @see #SpringApplication(ResourceLoader, Object...)
*/
//第一步: springboot 容器的加载
// ./mvnw clean install -DskipTests -Pfast //跳过测试用例
public SpringApplication(Object... sources) {
initialize(sources);
}
org.springframework.boot.SpringApplication#initialize
// 第二步: 初始化 initialize
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
// 第一步: 设置环境
this.webEnvironment = deduceWebEnvironment();
// 第二步: 获取ApplicationContextInitializer,也是在这里开始首次加载spring.factories文件
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 第三步: 获取监听器,这里是第二次加载spring.factories文件
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class)该类就是读取
META-INF/spring.factories文件
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
进入到这个方法org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class)从META-INF/spring.factories路径加载
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
org.springframework.boot.SpringApplication#deduceMainApplicationClass 找到主类创建对象
private Class> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class) 获取工厂实例对象
private Collection extends T> getSpringFactoriesInstances(Class type) {
return getSpringFactoriesInstances(type, new Class>[] {});
}
private Collection extends T> getSpringFactoriesInstances(Class type, Class>[] parameterTypes,
Object... args) {
//获取当前类的类加载器
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames 通过类名加载类
public static List loadFactoryNames(Class> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
ArrayList result = new ArrayList();
while(urls.hasMoreElements()) {
// 统一资源定位符
URL url = (URL)urls.nextElement();
// 读取该路径下面的资源封装成属性配置文件
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
// 获取到属性配置文件中属于该类的实现类
String propertyValue = properties.getProperty(factoryClassName);
//分割、将多个类之间分割开来成一个一个的类路径
String[] var8 = StringUtils.commaDelimitedListToStringArray(propertyValue);
int var9 = var8.length;
// 添加到容器中
for(int var10 = 0; var10 < var9; ++var10) {
String factoryName = var8[var10];
result.add(factoryName.trim());
}
}
return result;
} catch (IOException var12) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var12);
}
}
前面是读取,既然读取了文件,肯定接下来就是创建对象。
org.springframework.boot.SpringApplication#createSpringFactoriesInstances 创建实例对象
这个类比较简单,就是基于反射创建对象
private List createSpringFactoriesInstances(Class type, Class>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set names) {
List instances = new ArrayList(names.size());
// 遍历
for (String name : names) {
try {
Class> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
介绍run方法
org.springframework.context.ConfigurableApplicationContext
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* @param source the source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
org.springframework.context.ConfigurableApplicationContext
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param sources the sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
前面介绍的是如何加载配置文件,后面介绍如和启动
public ConfigurableApplicationContext run(String... args) {
// 第一步: 时间监控 设置启动时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 第二步: 该类可以获取到bean的相关配置
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
// 第三步: 是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,
// 很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
configureHeadlessProperty();
// 第四步: 获取并启动监听器
//EventPublishingRunListener 比添加到对应的runner
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 第五步: 构造容器环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 第六步: 打印banner
Banner printedBanner = printBanner(environment);
// 第七步:创建容器
context = createApplicationContext();
// 第八步: 实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
analyzers = new FailureAnalyzers(context);
//第五步:准备容器
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//第六步:刷新容器
refreshContext(context);
//第七步:刷新容器后的扩展接口
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
获取并启动监听器 前面已经介绍过该类。
SpringApplicationRunListeners listeners = getRunListeners(args);
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}
org.springframework.boot.SpringApplication#createApplicationContext 创建容器
/**
* Strategy method used to create the {@link ApplicationContext}. By default this
* method will respect any explicitly set application context or application context
* class before falling back to a suitable default.
* @return the application context (not yet refreshed)
* @see #setApplicationContextClass(Class)
*/
protected ConfigurableApplicationContext createApplicationContext() {
Class> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
// 创建基于annotation的上下文对象
contextClass = Class.forName(this.webEnvironment ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
org.springframework.boot.SpringApplication#prepareContext 预处理上下文对象
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 执行初始化器 =》
applyInitializers(context);
// 执行监听器上下文准备事件 -》
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set
org.springframework.boot.SpringApplication#postProcessApplicationContext 后置处理器
/**
* Apply any relevant post processing the {@link ApplicationContext}. Subclasses can
* apply additional processing as required.
* @param context the application context
*/
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
// 获取资源加载器对象
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
//如果是该类 GenericApplicationContext
((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
}
//如果是该类 DefaultResourceLoader
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
}
}
}
org.springframework.boot.SpringApplication#applyInitializers 执行初始化器
/**
* Apply any {@link ApplicationContextInitializer}s to the context before it is
* refreshed.
* @param context the configured ApplicationContext (not refreshed yet)
* @see ConfigurableApplicationContext#refresh()
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
//获取到springboot上下文初始化对象
for (ApplicationContextInitializer initializer : getInitializers()) {
Class> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
// 初始化
initializer.initialize(context);
}
}
添加到ConfigurableApplicationContext 容器中。
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer#initialize
@Override
public void initialize(ConfigurableApplicationContext context) {
context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
}
//bean 的生命周期钩子
org.springframework.context.support.AbstractApplicationContext#addBeanFactoryPostProcessor
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
检查
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer#getChecks
/**
* Returns the checks that should be applied.
* @return the checks to apply
*/
protected Check[] getChecks() {
return new Check[] { new ComponentScanPackageCheck() };
}
// 扫面包对象
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck
// 静态初始化对象
static {
Set packages = new HashSet();
packages.add("org.springframework");
packages.add("org");
PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
}
springboot启动的时候组件扫描器会默认扫描这两个包
@Override
public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
List> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
applyInitializerClasses(context, initializerClasses);
}
}
private List> getInitializerClasses(ConfigurableEnvironment env) {
String classNames = env.getProperty(PROPERTY_NAME);
List> classes = new ArrayList>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
classes.add(getInitializerClass(className));
}
}
return classes;
}
默认初始化化类对象
org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializerClasses
private void applyInitializerClasses(ConfigurableApplicationContext context, List> initializerClasses) {
Class> contextClass = context.getClass();
List> initializers = new ArrayList>();
for (Class> initializerClass : initializerClasses) {
initializers.add(instantiateInitializer(contextClass, initializerClass));
}
applyInitializers(context, initializers);
}
org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializers
private void applyInitializers(ConfigurableApplicationContext context,
List> initializers) {
Collections.sort(initializers, new AnnotationAwareOrderComparator());
for (ApplicationContextInitializer initializer : initializers) {
initializer.initialize(context);
}
}
listeners.contextPrepared(context);
org.springframework.boot.SpringApplicationRunListeners#contextPrepared
public void contextPrepared(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {、
// 添加到listener中
listener.contextPrepared(context);
}
}
load(context, sources.toArray(new Object[sources.size()]));
/**
* Load beans into the application context.
* @param context the context to load beans into
* @param sources the sources to load
*/
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Object)
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class>) {
return load((Class>) source);
}
if (source instanceof Resource) {
return load((Resource) source);
}
if (source instanceof Package) {
return load((Package) source);
}
if (source instanceof CharSequence) {
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
org.springframework.boot.SpringApplication#afterRefresh
afterRefresh(context, applicationArguments);
/**
* Called after the context has been refreshed.
* @param context the application context
* @param args the application arguments
*/
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
callRunners(context, args);
}
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List
/**
* Interface used to indicate that a bean should run when it is contained within
* a {@link SpringApplication}. Multiple {@link ApplicationRunner} beans can be defined
* within the same application context and can be ordered using the {@link Ordered}
* interface or {@link Order @Order} annotation.
*
* @author Phillip Webb
* @since 1.3.0
* @see CommandLineRunner
*/
public interface ApplicationRunner {
/**
* Callback used to run the bean.
* @param args incoming application arguments
* @throws Exception on error
*/
void run(ApplicationArguments args) throws Exception;
}
org.springframework.boot.SpringApplicationRunListeners#finished
listeners.finished(context, null);
private void callFinishedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
Throwable exception) {
try {
listener.finished(context, exception);
}
catch (Throwable ex) {
if (exception == null) {
ReflectionUtils.rethrowRuntimeException(ex);
}
if (this.log.isDebugEnabled()) {
this.log.error("Error handling failed", ex);
}
else {
String message = ex.getMessage();
message = (message != null) ? message : "no error message";
this.log.warn("Error handling failed (" + message + ")");
}
}
}
执行监听器的spring上下文加载完毕事件