这里写自定义目录标题
- Springboot的核心功能是什么
- Springboot注解
- 自动配置的原理
- 其他的一些注解
- Springboot的运行流程
- 1、mian方法
- 2、执行run方法
- Springboot配置文件的加载顺序
Springboot的核心功能是什么
1、运行独立的spring 项目
Spring Boot 可以以 jar 包的形式独立运行,运行一个 Spring Boot 项目只需通过 java–jar xx.jar 来运行。
2、内嵌的servet容器
可选择内嵌的tomcat,无需打包成war部署项目
3、提供starter简化maven配置
springboot提供了starter pom从而简化了maven的配置
4、自动配置spring
Springboot注解
一、首先我们先看springboot的运行代码
@SpringBootApplication
public class NotesApplication {
public static void main(String[] args) {
SpringApplication.run(NotesApplication.class, args);
}
}
其中@SpringBootApplication是springboot中的核心注解,它包括了三个注解:
- @Configuration
- @EnableAutoConfiguration
- @ComponentScan
相当于:@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan。
1、Configuration:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
........
}
Configuration这个注解是定义配置类的,可以替换spring中的xml配置文件
xml的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<!--bean定义-->
</beans>
基于Configuration注解的配置:
@Configuration
2 public class MockConfiguration{
3 //bean定义
4 }
2、@ComponentScan
对应xml中的配置元素,它自动扫描加载符合条件的组件或者bean,最终将这些bean定义加载到当前使用的容器中,非必须的。
3、@EnableAutoConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
.......
}
它帮助springboot把所以符合条件的@Configuration配置类都加载到当前SpringBoot创建并使用的IoC容器中
SpringFactoriesLoader:
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap();
private SpringFactoriesLoader() {
}
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
......
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
.......
}
}
SpringFactoriesLoader主要功能就是从指定的配置文件META-INF/spring.factories中加载配置
自动配置的原理
Spring Boot启动的时候会通过@EnableAutoConfiguration注解(SpringFactoriesLoader)找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载
其他的一些注解
二、其他的一些注解:
1、@Autowired:注入依赖bean,按name注入。
2、@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。
3、@Bean:用@Bean标注方法等价于XML中配置的bean。
4、@Value:注入Spring boot application.properties配置的属性的值
5、@Resource(name=”name”,type=”type”):没有括号内内容的话,默认byName
6、@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。
Springboot的运行流程
springboot启动后的大致流程:springboot启动后,run方法完成了springboot的启动流程:准备Environment ----->发布事件------>创建上下文,bean ------>刷新上下文------->结束,中间穿插了一系列的监听器的动作。
接下来我们看一看源码相关的东西
1、mian方法
@SpringBootApplication
public class NotesApplication {
public static void main(String[] args) {
SpringApplication.run(NotesApplication.class, args);
}
}
mian方法做了两件事:1)new 了一个SpringApplication 2)调用run方法,加载接口实例
2、执行run方法
初始化springboot后,执行run方法
public ConfigurableApplicationContext run(String... args) {
//计时器,统计任务的执行时间
StopWatch stopWatch = new StopWatch();
//开始执行
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
this.configureHeadlessProperty();
// 获取SpringApplicationRunListeners启动事件监听器,这里只有一个EventPublishingRunListener
SpringApplicationRunListeners listeners = this.getRunListeners(args);
// 封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听
listeners.starting();
try {
// 构造一个应用程序参数持有类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备并配置环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
// 打印banner图形
Banner printedBanner = this.printBanner(environment);
// 创建Spring容器
context = this.createApplicationContext();
new FailureAnalyzers(context);
// 配置Spring容器
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 容器上下文刷新
this.refreshContext(context);
// 容器创建完成之后调用afterRefresh方法
this.afterRefresh(context, applicationArguments);
// 调用监听器,广播Spring启动结束的事件
listeners.finished(context, (Throwable)null);
// 停止计时器
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}
1)获取启动监听器,启动时间监听器
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
2)配置并且准备环境
判断环境,如果是web程序,创建StandardServletEnvironment;否则,创建StandardEnvironment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
3)创建spring上下文
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch(this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}
return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
配置spring上下文
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
4)spring文件创建后返回回调方法
postProcessApplicationContext
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", this.beanNameGenerator);
}
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext)context).setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader)context).setClassLoader(this.resourceLoader.getClassLoader());
}
}
if (this.addConversionService) {
context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
}
}
5)spring容器创建完成后回调afterRefresh
Springboot配置文件的加载顺序
1)properties文件;
2)YAML文件;
3)系统环境变量;
4)命令行参数;