代码实现github:github.com/Ccww-lx/Spr…
SpringBoot作为我们日常开发的框架,我们必须熟悉掌握SpringBoot基础核心,包括SpringBoot运行原理、基础配置、外部配置、日志配置、Profile配置、核心注解等等,其中:
SpringBoot运行原理:
- 入口类和@SpringBootApplication
- Starter pom
核心注解:
- 注解解析
- 自定义
基础配置:
- banner配置
- Spring Boot配置文件(properties、yaml)
- xml文件配置
外部配置:
- 命令行参数配置
- 常规属性配置、类型安全的配置
日志配置:
- 支持Log4J、Log4J2以及Logback(默认)
Profile配置:
- 不同环境对应不同配置:application-{profile}.properties
基础配置
banner配置
在src/main/resources下新建一个banner.txt,banner.txt可以通过网站生成字符自动生成。启动闭关代码如下:
@SpringBootApplication public class BaseSpringBootApplication { public static void main(String[] args) { //关闭banner SpringApplication application = new SpringApplication(BaseSpringBootApplication.class); //application.setBannerMode(Banner.Mode.OFF); application.run(); //使用fluent API修改 /* new SpringApplicationBuilder(BaseSpringBootApplication.class) .bannerMode(Banner.Mode.OFF) .run();*/ } } 复制代码
Spring Boot配置文件(properties、yaml)
可使用配置文件application.properties或application.yml, 放置在src/main/resources目录下的任何目录下。如下图所示:
xml文件配置
可使用注解@ImportResource来加载xml配置,更加spring boot的灵活性。代码如下:
//导入Spring的配置文件,让配置文件里面的内容生效 @ImportResource(locations = {"classpath:base.xml"}) @Configuration public class LoadXmlFileConfiguration { //加载base.xml文件下的bean到IOC容器中 } 复制代码
外部配置
命令行参数配置
可以直接在启动时通过命令行进行配置,如下:
java -jar xxx.jar --server.port=8888 复制代码
更多详细参数使用可以查看。
常规属性配置、类型安全的配置
通过@Value注入值,只需在properties或者yaml文件中定义属性, 直接使用@Value注入即可,也通过@ConfigurationProperties将properties或者yaml属性和一个Bean及其属性关联, 从而实现类型安全的配置。代码如下所示:
//通过@ConfigurationProperties加载properties文件属性 //可使用perfix前缀指定加载properties文件属性,通过location加载指定文件 @ConfigurationProperties(prefix = "project") @Configuration public class AutoConfigurationProperties { @Value("${project.name}") private String projectName; @Value("project.author") private String projectAuthor; public String getServerInfo() { System.out.println("projectName:" + projectName + "projectAuthor:" + projectAuthor); return "projectName:" + projectName +" ----" + "projectAuthor:" + projectAuthor; } } 复制代码
日志配置
Spring Boot默认使用Logback作为日志框架,也支持Java Util Logging、 Log4J、 Log4J2。
log从高到低级别:
- OFF Level:最高等级的,用于关闭所有日志记录
- FATAL level:指出每个严重的错误事件将会导致应用程序的退出
- ERROR level:指出虽然发生错误事件,但仍然不影响系统的继续运行
- WARN level:明会出现潜在错误的情形
- INFO level:应用程序的运行过程
- DEBUG Level:调试应用级别
- TRACE :记录事件消息
- ALL:是最低等级的,用于打开所有日志记录
日志配置如下:
<?xml version="1****.0" encoding="UTF-8"?> <Configuration status="WARN"> <Properties> <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> <Property name="LOG_LEVEL_PATTERN">%5p</Property> <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property> <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> <Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} %pid --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> </Properties> <Appenders> <Console name="Console" target="SYSTEM_OUT" follow="true"> <PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" /> </Console> </Appenders> <Loggers> <Logger name="com.cn.ccww.*" level="info" /> <Root level="info"> <AppenderRef ref="Console" /> </Root> </Loggers> </Configuration> 复制代码
Profile配置
不同环境对应不同配置:application-{profile}.properties,并通过在application.properties中设置 spring.profiles.active=prod来指定活动的Profile。如下图所示:
SpringBoot运行原理
入口类和@SpringBootApplication
通常定义一个XXXApplication的类并使用@SpringBootApplication注解作为启动类, 入口类里有一个main方法,并使用SpringApplication.run( XXXApplication.class, args) , 启动Spring Boot应用项目。
@SpringBootApplication是Spring Boot的核心注解, 它是一 个组合注解,它的核心功能是由@EnableAutoConfiguration注解提供,并由@Import注解导入EnableAutoConfigurationImportSelector类实现自动配置。
@SpringBootApplication源码:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { .... } 复制代码
详细@SpringBootApplication源码可以查看文章【简明易理解的@SpringBootApplication注解源码分析】
Starter pom
Spring Boot为我们提供了简化企业级开发绝大多数场景的starter pom, 只要使用了应用场景所需要的starter pom, 相关的 技术配置将会消除, 就可以得到Spring Boot为我们提供的自动配置的Bean。
常见starter:
名称 | 描述 |
spring-boot-starter | Spring Boot核心starter,包含自动配置、日志、yaml配置文件支持 |
spring-boot-starter-activemq | 为JMS使用Apache ActiveMQ |
spring-boot-starter-amqp | 使用Spring AMQP、Rabbit MQ |
spring-boot-starter-aop | 通过Spring AOP、AspectJ面向切面编程 |
spring-boot-starter-cache | 使用 Spring caching缓存支持 |
spring-boot-starter-data-cassandra | 使用Cassandra分布式数据库、Spring Data Cassandra |
spring-boot-starter-data-elasticsearch | 使用Elasticsearch、analytics engine、Spring Data Elasticsearch |
spring-boot-starter-data-jdbc | 通过 Tomcat JDBC 连接池使用JDBC |
spring-boot-starter-data-jpa | 通过 Hibernate 使用 Spring Data JPA (Spring-data-jpa依赖于Hibernate) |
spring-boot-starter-data-mongodb | 使用 MongoDB 文件存储数据库、Spring Data MongoDB |
spring-boot-starter-data-neo4j | 使用Neo4j图形数据库、Spring Data Neo4j |
spring-boot-starter-data-redis | 通过Spring Data Redis 、Jedis client使用Redis键值存储数据库 |
spring-boot-starter-data-rest | 使用Spring Data REST 以 REST 方式暴露 Spring Data repositories |
spring-boot-starter-data-solr | 通过 Spring Data Solr 使用 Apache Solr搜索引擎 |
spring-boot-starter-freemarker | 使MVC Web applications 支持 FreeMarker,类似JSP |
spring-boot-starter-groovy-templates | 使MVC Web applications 支持Groovy Templates |
spring-boot-starter-integration | 使用Spring Integration,Spring Integration是Spring框架创建的一个API,面向企业应用集成(EAI) |
spring-boot-starter-json | 使用Json读写 |
spring-boot-starter-mail | 使用Java Mail、Spring email发送支持 |
spring-boot-starter-oauth2-client | 使用Spring Security’s OAuth2或者OpenID连接客户端 |
spring-boot-starter-quartz | 使用Quartz scheduler |
spring-boot-starter-security | 使用 Spring Security安全框架 |
spring-boot-starter-test | 测试 Spring Boot applications包含JUnit、 Hamcrest、Mockito |
spring-boot-starter-thymeleaf | 使MVC Web applications 支持Thymeleaf,类似JSP |
spring-boot-starter-validation | 通过Hibernate Validator使用 Java Bean Validation,Bean Validation 是一个数据验证的规范;Hibernate Validator是一个数据验证框架 |
spring-boot-starter-web | 构建Web,包含RESTful风格框架SpringMVC和默认的嵌入式容器Tomcat |
spring-boot-starter-webflux | 支持使用Spring Framework’s Reactive Web构建WebFlux applications |
spring-boot-starter-websocket | 使用Spring WebSocket构建 WebSocket 应用 |
更多详细strater可以查看官方文档13.5 Starters
自定义starter
自定义Starter可以查看【SpringBoot】--自定义starter(原理以及代码实现)】
核心注解
核心注解的条件注解在org.springframwork.boot.autoconfigure.condition包下,其都由元注解@Conditional组合而成。更多的注解详情可查看文章【推荐收藏系列:Spring boot 2.x注解Annotation大全(持续更新....)】。
注解 | 解析 |
@ConditionalOnBean | 当容器里有指定的Bean的条件下。 |
@ConditionalOnClass | 当类路径下有指定的类的条件下。 |
@ConditionalOnExpression | 基于SpEL表达式作为判断条件。 |
@ConditionalOnJava | 基于JVM版本作为判断条件。 |
@ConditionalOnJndi | 在JNDI存在的条件下查找指定的位置。 |
@ConditionalOnMissingBean | 当容器里没有指定Bean的情况下。 |
@ConditionalOnMissingClass | 当类路径下没有指定的类的条件下。 |
@ConditionalOnNotWebApplication | 当前项目不是Web项目的条件下。 |
@ConditionalOnProperty | 指定的属性是否有指定的值。 |
@ConditionalOnResource | 类路径是否有指定的值。 |
@ConditionalOnSingleCandidate | 当指定Bean在容器中只有一个, 或者虽然有多个但是指定首选的Bean。 |
@ConditionalOnWebApplication | 当前项目是Web项目的条件下 |
源码分析:
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnMissingBean { ..... } 复制代码
其中,@Conditional的OnBeanCondition类为@ConditionalOnMissingBean的实现,可自定义,详情查看下节。
自定义conditional实现类:
实现一个是否windows系统条件的conditional实现类,代码如下:
//判断是否windows系统 public class WindowsCondition implements Condition { private final static String WINDOWS="Windows"; /** * ConditionContext:判断条件能使用的上下文(环境) * AnnotatedTypeMetadata:注释信息 */ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //获取当前环境变量 Environment environment=conditionContext.getEnvironment(); //获取bean注册器 BeanDefinitionRegistry registry = conditionContext.getRegistry(); //能获取到ioc使用的beanfactory ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); //获取环境变量中操作系统 String property = environment.getProperty("os.name"); //判断操作系统是否为windows if(property.contains(WINDOWS)){ //判断是否存在baseWindowsSevice类,不存在则进行bean注册 boolean isWindowsSevice = registry.containsBeanDefinition("baseWindowsSevice"); if(!isWindowsSevice){ //指定Bean定义信息;(Bean的类型,Bean的一系列信息) RootBeanDefinition beanDefinition = new RootBeanDefinition(BaseWindowsService.class); //注册一个Bean,指定bean名 registry.registerBeanDefinition("baseWindowsSevice", beanDefinition); BaseWindowsService windowsSevice = (BaseWindowsService)beanFactory.getBean("baseWindowsSevice"); windowsSevice.addServiceName("ccww---baseWindowsSevice"); } return true; } return false; } }