入口SpringApplication.run()
@SpringBootApplication
public class SpringBootStudyConfigApplication
public static void main(String[] args) {
SpringApplication.run(SpringBootStudyConfigApplication.class, args);
}
}
认识@SpringBootApplication注解
是 @Configuration @EnableAutoConfiguration @ComponentScan 三个注解的复合
请注意它的返回值:ConfigurableApplicationContext
SpringApplication 构造方法解读
疑问:
1、ApplicationContextInitializer是做什么用的? 请了解它的接口注释、方法注释、实现类有哪些。 2、 ApplicationListener是做什么用的?
SpringApplication.run()实例方法解读
环境准备过程解读
疑问:
1、参数配置在哪里完成的加载?
在学习参数配置时学习到了一个很重要的类 ConfigFileApplicationListener 。了解到在它里面完成的加载,它又是 在何时被谁调用的呢?
ConfigFileApplicationListener 的类定义
它是一个EnvironmentPostProcessor,也是一个ApplicationListener,应该就是通过它们来完成的调用!
1)实现的EnvironmentPostProcessor方法,在这里完成了加载配置文件的工作。
2) 实现的ApplicationListener方法
问: ApplicationEnvironmentPreparedEvent这个事件会在哪里发布?
想要看它的加载执行过程怎么办? 在加载的代码处打个断点就可以看到完整的加载过程了!
ConfigurableApplicationContext 创建与准备过程解读
1.ConfigurableApplicationContext 创建
createApplicationContext()
默认的三个常量类名是什么?
2.准备过程
3.刷新过程
4.auto configuration的bean定义加载:
问题:1、META-INF/spring.factories中指定的auto configuration Bean定义在哪里完成的加载? 整个过程的代码已看完,没看到这块代码,代码茫茫,如何找到加载它们的代码?
思考:一定会从META-INF/spring.factories中加载,加载的方法是哪个? 前面的代码中已见过从META-INF/spring.factories中加载其他的:
那就从这个getSpringFactoriesInstances(...)方法调用中找到一个合适的点,打个断点来看谁会加载自动配置
看到,它是调用的SpringFactoriesLoader.loadFactoryNames(type, classLoader));
在它上打个断点,来看什么时候会加载自动配置的配置类:
得到调用栈:
从调用栈看到是在进行ConfigurationClassPostProcessor处理阶段
其实,秘密在@SpringBootApplication复合的 @EnableAutoConfiguration 注解
AutoConfigurationImportSelector 干的这个事
重点说明:AutoConfigurationImportSelector 实现了 DeferredImportSelector
DeferredImportSelector 是延迟导入选择器。所谓延迟:在所有指定的、包扫描到的@Configuration类中的 bean定义注册后,才会来处理延迟导入的@Configuration类
疑问:
1、这里自动配置为什么要以DeferredImportSelector 延迟导入的方式? 答案:让我们自己编程配置的bean提前注册,这样自动配置时的条件判断能发现到我们配置的,就能做到不再配置 自动配置的bean等。比如:如果我们自己配置了数据源bean,则使用我们配置的数据源,不在自动配置数据源。数 据源自动配置的代码中可以看到@ConditionalOnMissingBean({ DataSource.class, XADataSource.class }):
5.callRunners(context, applicationArguments) 解读
在代码中我们看到,从applicationContext 获取了所有 ApplicationRunner、CommandLineRunner类型的bean, 并执行了它们的run方法。
疑问
1、ApplicationRunner 是什么?有什么用?
2、CommandLineRunner是什么?有什么用? 两个是同样的用途:当ApplicationContext刷新好后,来执行你的应用逻辑。
示例:
除此之外,你还有什么方式来执行应用逻辑吗?
6.Tomcat是如何跑起来的?
从创建ApplicationContext处开始
看AnnotationConfigServletWebServerApplicationContext类
看它的父类ServletWebServerApplicationContext
WebServer的创建过程:
onRefresh()方法是AbstractApplicationContext中定义的供子类实现的空模板方法,在refresh()方法中被调用。
看它里面的getWebServerFactory():从容器中找ServletWebServerFactory类型的Bean,只能有一个。
再看通过factory.getWebServer()得到WebServer,先看接口定义:
在ServletWebServerApplicationContext中可以看到做这个start动作的方法:
TomcatServletWebServerFactory中的实现:
疑问:TomcatServletWebServerFactory这个Bean哪里配置的? 在spring boot 的自动配置中可以找到
看 ServletWebServerFactoryAutoConfiguration
看ServletWebServerFactoryConfiguration.EmbeddedTomcat.class
看到 @EnableConfigurationProperties(ServerProperties.class)
可以配置哪些服务器参数:
再来看下tomcat可以配置什么参数
参数配置示例: application.yml
7.spring boot web 中集成 Servlet api
1、使用 Servlet Filter 有两种方式
方式一 servelt3.0 注解 + @ServletComponentScan
方式二:ServletRegistrationBean和FilterRegistrationBean注册方式
2、jsp做视图技术
spring boot 不推荐使用jsp。
集成jsp的步骤:
1、引入对应的jar
2、创建jsp文件放置目录 src/main下创建 webapp/WEB-INF/jsp/
3、在application.yml中配置spring.mvc.view
4、编写Controller jsp
5、运行、测试