根据之前的学习,在搭建springboot项目时,我们可以简化很多配置。那springboot是如何做到的呢?
首先我们来看JAVA WEB的启动过程
点这里
web项目需要部署容器(tomcat\weblogic等),容器会首先加载web项目中的 web.xml文件。
项目的启动顺序首先是context-param,接着是listener,在接下来是filter,最后才是servlet。
知识点 过滤器和拦截器
SpringMVC
springmvc的启动过程也是基于上述过程。
tomcat容器 会将读取到<context-param>转化为键值对,并交给ServletContext(上下文) ,供整个WEB项目使用
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-*.xml</param-value>
</context-param>
在执行玩上下文加载后会建立监听,ServletContextListener作为监听类的根接口contextInitialized,contextDestroyed两个方法。
<!--监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
而 ContextLoaderListener 重写了 contextInitialized 方法
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
初始化Web应用上下文,initWebApplicationContext中调用configureAndRefreshWebApplicationContext对IoC容器的配置和刷新操作。
该方法主要用于创建并初始化contextConfigLocation类配置的xml文件中的Bean,因此,如果我们在配置Bean时出错,在Web应用启动时就会抛出异常,而不是等到运行时才抛出异常。
filter初始化
servlet初始化
常用DispatcherServlet类,DispatcherServlet类间接父类实现了Servlet接口,创建一个IOC子容器,并加载<servlet>标签的<init-param>配置的xml文件并加载相关Bean。
SpringBoot的启动过程
spring boot
我们来看springboot的启动类
@SpringBootApplication
@Slf4j
public class Application
{
public static void main(String[] args)
{
log.info("=================开始成功=================");
SpringApplication.run(Application.class, args);
log.info("=================启动成功=================");
}
@SpringBootApplication注解是springboot启动的开始,我们来看看
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class))
public @interface SpringBootApplication {
Class<?>[] exclude() default {};
String[] excludeName() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 是其中最重要的三个注解
@SpringBootConfiguration 注解
@SpringBootConfiguration其实就是@Configuration,熟悉spring的都知道,@Configuration 是一个类级注释,指示对象是一个bean定义的源。@Configuration 类通过 @bean 注解的公共方法声明bean。减少xml配置。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
例如:
<beans>
<bean id="orderService" class="com.acme.OrderService"/>
<constructor-arg ref="orderRepository"/>
</bean>
<bean id="orderRepository" class="com.acme.OrderRepository"/>
<constructor-arg ref="dataSource"/>
</bean>
</beans>
使用@Configuration
@Configuration
public class ApplicationConfig {
public @Bean OrderService orderService() {
return new OrderService(orderRepository());
}
public @Bean OrderRepository orderRepository() {
return new OrderRepository(dataSource());
}
public @Bean DataSource dataSource() {
}
}
@ComponentScan告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。
@EnableAutoConfiguration
点这里
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
@EnableAutoConfiguration让Spring Boot根据类路径的jar包依赖为当前项目进行自动化配置。
例如,添加了spring-boot-starter-web依赖,会自动添加Tomcat和Spring MVC的依赖,那么Spring Boot会对Tomcat和Spring MVC进行自动配置。
又如,添加了spring-boot-starter-data-jpa依赖,Spring Boot会自动进行JPA相关的配置。
进入@EnableAutoConfiguration
查看getCandidateConfigurations方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
SpringFactoriesLoader.loadFactoryNames加载META-INF/spring.factories文件中jar文件
例如spring-boot-1.4.2.RELEASE.jar 中的META-INF/spring.factories
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer
# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
我们在springmvc中使用redis
spring+redis
需要配置一些bean,如:
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<!--开启事务 -->
<property name="enableTransactionSupport" value="true"></property>
</bean>
才可以使用
@Autowired
public RedisTemplate redisTemplate;
在springboot中
可以直接从容器中拿去RedisTemplate bean对象
在spring-boot-autoconfigure依赖包中有一个spring.factories文件
查看 这个RedisAutoConfiguration类
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}