-
不同于spring MVC,springboot是内嵌服务器。spring MVC需要依靠tomcat来启动,而springboot不需要,两者的启动顺序不同。
- spring MVC是先启动tomcat服务器 ,在创建spring容器,springboot是先创建spring容器,在启动tomcat服务器。
springboot流程
- new SpringApplication():创建SpringApplication实例,负责加载配置一些基本的环境变量、资源、构造器、监听器
- run():负责springboot整个启动过程,包括加载创建环境、打印banner、配置文件、配置应用上下文,加载bean等等springboot整个生命周期几乎都在run方法中;
手写一个极简@SpringbootApplication注解
- 创建一个含@Component和@ComponentScan的注解类。
- 创建一个启动类,内容包括spring容器创建和tomcat容器创建和启动,并将spring容器添加只servlet中
- 用@Bean方式创建一个dispatcherServlet。(此处可随意)
示例:
1.注解PrincipleSpringBootApplication:
package springBoot.principle.boot;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Configuration
@ComponentScan //ComponentScan默认扫描注解类所在的包
public @interface PrincipleSpringBootApplication {
}
2.启动类PrincipleSpringApplication :
package springBoot.principle.boot;
import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
/**
* springboot主要实现方式
*/
public class PrincipleSpringApplication {
public static ConfigurableApplicationContext run(Class config) {
//创建annotation形式的spring web容器,继承自AbstractApplicationContext
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(config);
applicationContext.refresh();//Spring创建容器的核心方法
startTomcat(applicationContext);
return applicationContext;
}
/**
* Tomcat启动方法,主要都是添加tomcat启动所需的配置
*
* @param applicationContext
*/
private static void startTomcat(AnnotationConfigWebApplicationContext applicationContext) {
Tomcat tomcat = new Tomcat();
Server server = tomcat.getServer();
Service service = server.findService("Tomcat");
Connector connector = new Connector();
connector.setPort(8081);
Engine engine = new StandardEngine();
engine.setDefaultHost("localhost");
Host host = new StandardHost();
host.setName("localhost");
String contextPath = "";
Context context = new StandardContext();
context.setPath(contextPath);
context.addLifecycleListener(new Tomcat.FixContextListener());
host.addChild(context);
engine.addChild(host);
service.setContainer(engine);
service.addConnector(connector);
//创建dispatcherServlet,并将spring容器bean添加到servlet中
//DispatcherServlet bean=new DispatcherServlet(applicationContext);
DispatcherServlet servlet = applicationContext.getBean(DispatcherServlet.class);
//配置servlet映射
tomcat.addServlet(contextPath, "dispatcher", servlet);
context.addServletMappingDecoded("/*", "dispatcher");
try {
tomcat.start();
} catch (LifecycleException e) {
e.printStackTrace();
}
}
}
3.使用@PrincipleSpringBootApplication并自定义一个dispatcherServlet
package springBoot.principle;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;
import springBoot.principle.boot.PrincipleSpringApplication;
import springBoot.principle.boot.PrincipleSpringBootApplication;
@PrincipleSpringBootApplication
public class SpringBootTest {
@Bean
public DispatcherServlet dispatcherServlet(){
DispatcherServlet dispatcherServlet=new DispatcherServlet();
//提供可供自定义编辑的dispatcherServlet,此处可自行添加其他逻辑
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
public static void main(String[] args) {
PrincipleSpringApplication.run(SpringBootTest.class);
}
}
springboot的自动配置
- springboot采用的约定配置的方式,即按现有的开发习惯来定义好spring mvc中需要的配置。
- 在springboot核心模块springboot starter中引入了springboot autoconfigure模块,而在autoconfigure的resources中有spring.factories文件,其中包含了springboot的所有配置类,在springboot启动时通过类SPI方式启动,将所有的配置都当作bean存入spring容器中。
可参考源码进行相应的修改:SpringFactoriesLoader中的loadSpringFactories()方法
- 例如默认端口号8080就在AbstractConfigurableWebServerFactory中被定义。
配置文件application.yml的加载方式
- 通过debug可知,入口在SpringApplication中的prepareEnvironment方法。
- 最后在ConfigFileApplicationListener中的addPropertySources方法中。
Server属性的配置读取在ServletFactoryCustomize.java中的customize()方法中,在BeanPostProcessor中传递进来。
application.yml中服务器server有关的加载内容在ServerProperties.java中。