Spring Boot学习笔记-6

Spring Boot学习笔记-6

一、启动配置原理

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args)
{
	return run(new Class<?>[] { primarySource }, args);
}
//先创建一个SpringApplication对象,再执行run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) 
{
	return new SpringApplication(primarySources).run(args);
}
(1)创建SpringApplication对象
public SpringApplication(Class<?>... primarySources) 
{
	this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) 
{
    //保存主配置类
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	
    //判断是否为web应用
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    
   	//导入启动加载器
	this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
    
	//从类路径下找到META-INF/spring.factories配置的ApplicationContextInitializer并保存
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    
    //从类路径下找到META-INF/spring.factories配置的ApplicationListener并保存
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    
    //确定主程序
	this.mainApplicationClass = deduceMainApplicationClass();
}

在这里插入图片描述
在这里插入图片描述

(2)执行run方法
public ConfigurableApplicationContext run(String... args) 
{
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	DefaultBootstrapContext bootstrapContext = createBootstrapContext();
	ConfigurableApplicationContext context = null;
	configureHeadlessProperty();
    
    
    //获取SpringApplicationRunListeners
	SpringApplicationRunListeners listeners = getRunListeners(args);
    //回调获取到的SpringApplicationRunListeners的starting方法
	listeners.starting(bootstrapContext, this.mainApplicationClass);
    
    
   	//封装命令行参数
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        
        //准备环境,完成后回调listeners的environmentPrepared方法
		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		configureIgnoreBeanInfo(environment);
        
        //打印图标
		Banner printedBanner = printBanner(environment);
        
        //创建Applicationcontext,决定ioc容器类型
		context = createApplicationContext();
		context.setApplicationStartup(this.applicationStartup);
        
        //准备上下文
        //applyInitializers(context)回调之前保存的ApplicationContextInitializer的Initialize方法
        //listeners.contextPrepared(context)回调之前保存的ApplicationListener的contextPrepared方法
        //最后回调listeners.contextLoaded(context)
		prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        
        //刷新容器(扫描、创建、加载所有组件),ioc容器初始化
		refreshContext(context);
        
        //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
        //二者的功能都是在Spring容器初始化完毕之后执行起run方法
		//不同在于前者的参数是ApplicationArguments,对参数进行了封装,后者的参数是String...args,直接传入字符串
    	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, listeners);
		throw new IllegalStateException(ex);
	}
    
	try {
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, null);
		throw new IllegalStateException(ex);
	}
    
    //返回ioc容器
	return context;
}
private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
	return new SpringApplicationRunListeners(logger,
			getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
			this.applicationStartup);
}
	ApplicationContextFactory DEFAULT = (webApplicationType) -> {
		try {
			switch (webApplicationType) {
			case SERVLET:
				return new AnnotationConfigServletWebServerApplicationContext();
			case REACTIVE:
				return new AnnotationConfigReactiveWebServerApplicationContext();
			default:
				return new AnnotationConfigApplicationContext();
			}
		}
		catch (Exception ex) {
			throw new IllegalStateException("Unable create a default ApplicationContext instance, "
					+ "you may need a custom ApplicationContextFactory", ex);
		}
	};
//反射
static ApplicationContextFactory ofContextClass(Class<? extends ConfigurableApplicationContext> contextClass) 
    {
		return of(() -> BeanUtils.instantiateClass(contextClass));
	}

	private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);
		postProcessApplicationContext(context);
        
        
		applyInitializers(context);
        
        
		listeners.contextPrepared(context);


		bootstrapContext.close(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
		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());
		}
		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[0]));
        
        
		listeners.contextLoaded(context);
	}

二、SpringMVC

1.SpringMVC工作原理

模型(Model)-视图(View)-控制器(controller)

(1)客户端(浏览器)发送请求,直接请求到 DispatcherServlet。

(2)DispatcherServlet 根据请求信息调用Handler Mapping,解析请求对应的 Handler。

(3)解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由Handler Adapter适配器处理。

(4)Handler Adapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑

(5)处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的视图。

(6)View Resolver 会根据逻辑 View 查找实际的 View。

(7)DispaterServlet 把返回的 Model 传给 View(视图渲染)

(8)把 View 返回给请求者(浏览器)


2.SpringMVC重要组件

1、前端控制器DispatcherServlet

作用:Spring MVC 的入口函数,接收请求,响应结果。用户请求到达前端控制器,DispatcherServlet调用其它组件处理用户请求

2、处理器映射器Handler Mapping

作用:根据请求的url查找Handler。Handler Mapping负责根据用户请求找到Handler即处理器(Controller)

3、处理器适配器Handler Adapter

作用:按照特定规则去执行Handler,通过Handler Adapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

4、处理器Handler

后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。

5、视图解析器View resolver

作用:进行视图解析,根据逻辑视图名解析成真正的视图(view),负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

6、视图View

View是一个接口,实现类支持不同的View类型(jsp、freemarker…)


3.视图解析器(View Resolver)
@Bean
public ViewResolver myViewResolver()
{
    return new myViewResolver();
}

private static class myViewResolver implements ViewResolver
{
    @Override
    public View resolveViewName(String s, Locale locale) throws Exception {
        return null;
    }
}

在这里插入图片描述


4.前端控制器(Dispatcher Servlet)

SpringBoot配置SpringMVC时会自动注册SpringMVC的前端控制器Dispatcher Servlet

DispatcherServletAutoConfiguration中:

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
				WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
			
    DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
					webMvcProperties.getServlet().getPath());
    
			registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
			registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
			multipartConfig.ifAvailable(registration::setMultipartConfig);
			return registration;
		}
}

5.SpringMVC扩展&接管
1)扩展SpringMVC

编写一个配置类(@Configuration),实现WebMvcConfigurer接口(不能标注@EnableWebMvc)

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //浏览器发送view请求也来到success页面
        registry.addViewController("/view").setViewName("success");
    }
}

在这里插入图片描述

2)全面接管SpringMVC

使用@EnableWebMvc,弃用SpringBoot对SpringMVC的自动配置(包括静态资源)

原理:

//WebMvcAutoConfiguration
//容器中无WebMvcConfigurationSupport时该自动配置类才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
//@EnableWebMvc
@Import(DelegatingWebMvcConfiguration.class)
//DelegatingWebMvcConfiguration.class
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值