特点:
(一)约定优于配置
90%以上的项目呢,配置都差不多,所以呢spring团队,就搞出了一个通用的配置,以后我们程序猿就不需要再去配置这些繁杂的配置了. 如果用的ssm,所有的maven依赖,版本,都需要我们程序猿去控制,去找依赖,并且互相配合依赖.依赖没有配合好,jar冲突,,出了问题就需要程序猿去解决,一般非常耗时的.
补充:约定优于配置也被称为习惯优于配置、约定大于配置
提示:全局配置名称,默认 application
配置文件优先级:有config>无configh properties > yml > yaml
(二)开箱即用
<!--引入web starter启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(三)程序入口
/*
springboot启动类,服务类
@SpringBootApplication是一个复合注解(包括@ComponentScan,和@SpringBootConfiguration,@EnableAutoConfiguration)
*/
@SpringBootApplication
public class Demo0817Application {
public static void main(String[] args) {
SpringApplication.run(Demo0817Application.class, args);
}
//main 程序的入口
}
(四)常用注解
字段 | 说明 |
---|---|
@ComponentScan | 自动扫描组件,可自发配置一些Bean |
@Configuration | 等同于 spring 的 XML 配置文件 |
@EnableAutoConfiguration | 根据jar依赖自动配置Spring应用 |
@SpringBootApplication | 给springBoot自动进行必要的配置(@Configuration ,@EnableAutoConfiguration 和 @ComponentScan) |
@ResponseBody | 异步获取数据 |
@Controller | 定义控制类 |
@RequestMapping | 负责URL到Controller中的具体参数的映射 |
@Import | 导入其他配置类 |
@ImportResourc | 加载xml配置文件 |
@Autowired | 自动导入依赖的Bean |
@Service | 修饰Server层 |
@Repository | 可以确保 DAO 或者 repositories 提供异常转译,这个注解修饰的 DAO 或者 repositories 类会被 ComponetScan 发现并配置,同时也不需要为它们提供 XML 配置项 |
@Bean | 等同于xml中配置的Bean |
@Value | 注入值给配置类 |
@Inject | 等同于@Autowired(无required 属性) |
@Component | 泛指组件 |
@Qualifier | 当有多个同一类型的 Bean 时,可以用 @Qualifier(“name”) 来指定。与 @Autowired 配合使用。@Qualifier 只描述符除了能根据名字进行注入,还能更详细的控制如何选择候选者 |
@Resource | @Resource(name=”name”,type=”type”) 默认 byName 与@Autowired类似 |
还有JPA和springMVC以及全局异常处理可通过超连接访问
SpringApplication初始化时主要做三件事情:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//1.根据classpath下是否存在(ConfigurableWebApplicationContext)判断是否要启动一个web applicationContext
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//2.SpringFactoriesInstances加载classpath下所有可用的ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//3.SpringFactoriesInstances加载classpath下所有可用的ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
代码如下:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//1.遍历SpringApplication初始化过程中加载的SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
//2.调用starting()监听SpringApplication的启动
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//3.加载SpringBoot配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
//4.设置banner属性
Banner printedBanner = printBanner(environment);
//5.创建ConfigurableApplicationContext(应用配置上下文)
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//6.将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//7.实例化bean
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
遍历SpringApplication初始化过程中加载的SpringApplicationRunListeners:
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
调用Starting()监听SpringApplication的启动:
public void starting() {
//遍历所有的SpringApplicationRunListener,调用starting()方法监听SpringApplication的启动
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
加载SpringBoot配置环境
加载SpringBoot配置环境,如果是通过web容器发布,会加载StandardEnvironment。将配置文件(Environment)加入到监听器对象中(SpringApplicationRunListeners)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
//如果environment不为空直接返回 || 如果是web环境则直接实例化StandardServletEnvironment类 || 如果不是web环境则直接实例化StandardEnvironment类
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境信息
configureEnvironment(environment, applicationArguments.getSourceArgs());
//通知所有的监听者,环境已经准备好了
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
初始化ConfigurableApplicationContext
public enum WebApplicationType {
/**
* The application should not run as a web application and should not start an
* embedded web server.
*/
// 应用程序不是web应用,也不应该用web服务器去启动
NONE,
/**
* The application should run as a servlet-based web application and should start an
* embedded servlet web server.
*/
//应用程序应作为基于servlet的web应用程序运行,并应启动嵌入式servlet web(tomcat)服务器
SERVLET,
/**
* The application should run as a reactive web application and should start an
* embedded reactive web server.
*/
//应用程序应作为 reactive web应用程序运行,并应启动嵌入式 reactive web服务器。
REACTIVE;
}
根据webEnvironment是否是web环境创建默认的contextClass,
AnnotationConfigEnbeddedWebApplicationContext(通过扫描所有注解类来加载bean)和ConfigurableWebApplicationContext),最后通过BeanUtils实例化上下文对象,并返回。
protected ConfigurableApplicationContext createApplicationContext() {
//根据webEnvironment是否是web环境创建默认的contextClass
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
//AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
//AnnotationConfigReactiveWebServerApplicationContext
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
//AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
ex);
}
}
//BeanUtils实例化上下文对象
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//设置上下文的environment
context.setEnvironment(environment);
//应用上下文后处理
postProcessApplicationContext(context);
//在context refresh之前,对其应用ApplicationContextInitializer
applyInitializers(context);
//上下文准备
listeners.contextPrepared(context);
//打印启动日志和启动应用的profile
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//向beanFactory注册单例bean:命令行参数bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
//向beanFactory注册单例bean:banner bean
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
//获取SpringApplication的primarySources属性
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//将bean加载到应用上下文
load(context, sources.toArray(new Object[0]));
//向上下文添加ApplicationListener,并广播ApplicationPreparedEvent事件
listeners.contextLoaded(context);
}
~bean的实例化完成