-
先部署项目,看效果:
报错1:"Dependency 'xxxx‘ not found"
"Project 'xxxx‘ not found"
原因:IDEA没有配置好maven,修改maven home directory、user settings file、local repository。
报错2:Plugin 'org.springframework.boot:spring-boot-maven-plugin:' not found
原因:pom.xml文件中中的 spring-boot-maven-plugin 没加版本号,版本号需要与项目springboot版本一致,此处为 2.3.7.RELEASE 。
报错3:Project ‘org.springframework.boot:spring-boot-starter-parent:2.4.5‘ not found
在使用IntelliJ IDEA 时出现这个问题,选择File—>Invalidate Caches / Restart…就可以解决这个问题,因为更新之后,缓存没有及时生效,重启之后就好了。
- 为什么框架的出现会取代原有 JSP+Servlet 的开发模式?
是因为框架的封装和抽象程度更加完善,也使得代码复用性更高、项目的可维护性提高、开发和学习成本更低,加快开发进度并最终成为行业内的一套开发标准。从这个角度来说,越简洁的开发模式就越能减轻开发人员的负担并提升开发效率
-
springboot的特性:
-
可快速创建Spring 项目,简化开发
Spring Initializr 方案是创建新的Spring Boot 项目不错的选择。使用官方的初始化方案创建 Spring Boot 项目能够确保你获得经过测试和验证的依赖项,这些依赖项适用于自动配置,能够大大简化项目创建流程。
-
starters 自动依赖与版本控制
Spring Boot 通过一些 starter 的定义减少开发人员在依赖管理上所花费的时间,在整合各项功能的时候不需要去自行搜索和查找所需依赖并且在 Maven 的 pom 文件中进行定义。
-
习惯优于配置
-
大量的自动配置,简化开发
-
使用嵌入式的servlet容器
-
对主流框架的无配置集成
在 Web 应用中,spring-boot-starter-web 为我们提供了嵌入的 Tomcat 以及 SpringMVC 的依赖, 可以快速构建 MVC 模式的 Web 工程。
在 SOA 及微服务中,用 Spring Boot 可以包装每个服务, Spring Cloud即是一套基于 Spring Boot 实现分布式系统的工具,适用于构建微服务。
spring-boot-starter-websocket 可以快速实现消息推送,也可以整合流行的 RPC 框架,提供 RPC 服务接口,只要简单地加入对应的 starter 组件即可。
-
4、项目搭建及启动
使用spring initializer搭建的web项目中:
src/main/resources 表示配置文件目录,与普通的 Spring 项目相比有些区别:该目录下有 static 和 templates 两个目录,是 Spring Boot 项目默认的静态资源文件目录和模板文件目录。在 Spring Boot 项目中是没有 webapp 目录的,默认是使用 static 和 templates 两个文件夹。
5、特性讲解与源码分析
5.1 特性讲解
-
约定优于配置
convention over configuration,这个理念不是springboot独有的,其实我们一直都在遵循并使用,比如在 MVC 项目的开发中会把实体类放到 entity 目录下、数据接口层会定义在 dao 目录下、控制器会定义在 controller 目录下,这就是大家都遵循的规矩。
如果在项目中遵守命名规范就可以显著地减少系统需要的配置,不然目录名、包名乱取名字这些都会使得配置难度增大。
-
依赖管理
在项目的
pom.xml文件中,可看到配置了 属性,意味着它依赖一个父项目,其父项目为spring-boot-starter-parent。它也拥有 属性,其值为spring-boot-dependencies。而
spring-boot-dependencies就是 springboot 项目依赖的版本管理中心。 它已经默认帮我们配置好了大部分依赖的版本信息,这些版本信息随着 Spring Boot 版本的更新也会随之更改。如果自行配置的话会将默认配置覆盖掉。 -
web场景启动器
在
spring-boot-starter-web中,已经定义了 SpringMVC 所需的依赖以及内置的 Tomcat 依赖。
5.2 基于主程序类的源码分析
主程序类如下:
@SpringBootApplication
public class Newbee810Application {
public static void main(String[] args) {
SpringApplication.run(Newbee810Application.class, args);
}
}
重点关注 @SpringBootApplication 注解 和 SpringApplication.run() 方法。
-
@SpringBootApplication
由注解源码可以看出,@SpringBootApplication 注解是一个复合注解,其中前面四个注解是 Java 元注解,含义分别为:
@Target(ElementType.TYPE): 类、接口(包括注解类型)和 enum 声明@Retention(RetentionPolicy.RUNTIME): 运行时注解@Documented: 注解添加到 Java doc 中@Inherited: 允许继承
重要的是后面三个 Spring Boot 框架的自定义注解,含义分别为:
-
@SpringBootConfiguration: Spring Boot 配置注解仅仅是对 @Configuration 注解进行了包装,本质上依然是 @Configuration 注解
-
@EnableAutoConfiguration: 开启自动配置功能除上面四个 Java 元注解外,这个注解最重要的就是 @AutoConfigurationPackage 和 AutoConfigurationImportSelector 组件。
-
@AutoConfigurationPackage,使用 @Import 注解,自动将AutoConfigurationPackages.Registrar.class 指定的组件注册到 IOC 容器中。默认情况下是当前主程序类所在的包及其子包 -
AutoConfigurationImportSelector,是整个自动配置功能的核心实现,会将所有需要导入的组件以全类名的方式返回,这些组件就会被注册到 IOC 容器中。public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { selectImports() getAutoConfigurationEntry() getImportGroup() isEnabled() getCandidateConfigurations() //getCandidateConfigurations() 方法会调用 SpringFactoriesLoader 类的 loadFactoryNames() 获取所有的自动配置类类名注意!上面代码实现的几个接口还未学习!到Spring教程中去看! 里面定义的几个方法也没有看!!!
由以上源码可以得出结论:Spring Boot 在启动的时候从类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的配置项,过滤后将这些值作为自动配置类导入到容器中。有哪些自动配置类呢?可以在 spring-boot-autoconfigure-2.1.0.RELEASE.jar 依赖中查看。
自动配置类生效之后,帮我们进行相关组件的自动配置工作,以前我们需要自己配置在 xml 文件中的内容都交给 Spring Boot 完成,免去了我们手动编写配置注入功能组件等的工作。
-
-
@ComponentScan: 组件自动扫描@Controller 、 @Service 、 @Repository 都有一个共同的注解 @Component,他们都会被@ComponentScan注解装配到 IOC 容器中。
-
SpringApplication.run()
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); // 1:代码执行时间监控开启,Spring Boot 应用启动成功后会打印启动时间 stopWatch.start(); DefaultBootstrapContext bootstrapContext = this.createBootstrapContext(); ConfigurableApplicationContext context = null; // 2:配置 headless 属性。 java.awt.headless是 J2SE 的一种模式,用于在缺失显示屏、鼠标或者键盘时的系统配置,默认为 true。 this.configureHeadlessProperty(); // 3:获取 SpringApplicationRunListeners。 getRunListeners()方法 会从类路径下的 META-INF/spring.factories 中获取 SpringApplicationRunListener 指定的类,此处为EventPublishingRunListener 。 SpringApplicationRunListeners listeners = this.getRunListeners(args); // 4:回调所有 SpringApplicationRunListener 对象的 starting() 方法。 listeners.starting(bootstrapContext, this.mainApplicationClass); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 5:preparedEnvironment 主要完成对 ConfigurableEnvironment 的初始化工作 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments); this.configureIgnoreBeanInfo(environment); // 6:获取打印的 Spring Boot 启动 banner 对象。默认实现为 org.springframework.boot.SpringBootBanner Banner printedBanner = this.printBanner(environment); // 7:创建 ApplicationContext 并配置 ApplicationContext 实例 context = this.createApplicationContext(); context.setApplicationStartup(this.applicationStartup); this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // 8:refreshContext() 刷新 ApplicationContext 对象。实现方法就是 Spring 的 refresh() 方法————Spring 所有的初始化都在这个方法中完成,。它会将之前通过 @EnableAutoConfiguration 获取的所有配置以及其他形式的 IOC 容器配置加载到已经准备完毕的ApplicationContext 对象中。 this.refreshContext(context); this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } listeners.started(context); // 9:在 ApplicationContext 完成启动后,会对 ApplicationRunner 和 CommandLineRunner 进行回调处理,查找当前ApplicationContext中是否注册有 CommandLineRunner,如果有,则遍历执行它们。 this.callRunners(context, applicationArguments); } catch (Throwable var10) { // 10:在 SpringApplication 启动过程中,如果出现问题会由异常处理器接管,对异常进行统一处理。 this.handleRunFailure(context, var10, listeners); throw new IllegalStateException(var10); } try { listeners.running(context); return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
Spring Boot 框架的核心依然是 Spring ,它只是在 Spring 框架的基础之上,针对 Spring 应用启动流程进行了规范和封装。Spring 的核心启动方法是 refresh() ,Spring Boot 在启动时依然会调用该核心方法,只是调用该方法之前已经设置了大部分组件,在平时的 Spring 项目开发中,这些组件通常是通过 xml 配置文件进行定义和装载,而 Spring Boot 将该过程简化并通过自动配置的方式去实现该过程,它只是基于 Spring 框架的一个增强版的应用启动器。