整理自:
博客园:龙四丶:SpringBoot系列java
SpringBoot 中运用了大量的 Spring 注解,其注解大体分为这几类:web
模式注解都标注了 @Component 注解,属于 @Component 的派生注解,@ComponentScan 会扫描标注 @Component 及其派生注解的类,并将这些类加入到 Spring 容器中;@Enable 模块注解中经过 @Import 导入配置类,在这些配置类中加载 @Enable 模块须要的组件。redis
模式注解是一种用于声明在应用中扮演“组件”角色的注解。如 Spring 中的 @Repository 是用于扮演仓储角色的模式注解,用来管理和存储某种领域对象。还有如@Component 是通用组件模式、@Service 是服务模式、@Configuration 是配置模式等。其中@Component 做为一种由 Spring 容器托管的通用模式组件,任何被 @Component 标注的组件均为组件扫描的候选对象。相似地,凡是被 @Component 标注的注解,如@Service ,当任何组件标注它时,也被视做组件扫描的候选对象。spring
@ComponentScan(basePackages = "com.loong.spring.boot") public class SpringConfiguration { }
注解的形式,依靠 basePackages 属性指定扫描范围。Spring 在启动时,会在某个生命周期内建立全部的配置类注解解析器,而 @ComponentScan 的处理器为 ComponentScanAnnotationParser。数据库
所谓“模块”是指具有相同领域的功能组件集合,组合所造成的一个独立的单元,好比 Web MVC 模块、AspectJ代理模块、Caching(缓存)模块、JMX(Java 管理扩展)模块、Async(异步处理)模块等。编程
Spring Boot和Spring Cloud版本中都一直被使用,这种模块化的注解均以 @Enable 做为前缀,以下所示:设计模式
框架实现 | @Enable注解模块 | 激活模块 |
---|---|---|
Spring Framework | @EnableWebMvc | Web Mvc 模块 |
/ | @EnableTransactionManagement | 事物管理模块 |
/ | @EnableWebFlux | Web Flux 模块 |
Spring Boot | @EnableAutoConfiguration | 自动装配模块 |
/ | @EnableConfigurationProperties | 配置属性绑定模块 |
/ | @EnableOAuth2Sso | OAuth2 单点登录模块 |
Spring Cloud | @EnableEurekaServer | Eureka 服务器模块 |
/ | @EnableFeignClients | Feign 客户端模块 |
/ | @EnableZuulProxy | 服务网关 Zuul 模块 |
/ | @EnableCircuitBreaker | 服务熔断模块 |
条件装配指的是经过一些列操做判断是否装配 Bean ,也就是 Bean 装配的前置判断。实现方式主要有两种:@Profile 和 @Conditional。数组
@Conditional(HelloWorldCondition.class) @Component public class HelloWorldConfiguration { public HelloWorldConditionConfiguration (){ System.out.println("HelloWorldConfiguration初始化。。。"); } } public class HelloWorldCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { // ... return true; } }
经过自定义一个 HelloWorldConfiguration 配置类,再标注 @Conditional 注解导入 HelloWorldCondition类,该类必须实现 Condition 接口,而后重写 matches 方法,在方法中能够经过两个入参来获取一系列的上下文数据和元数据,最终返回ture或false来断定该类是否初始化,缓存
二、自动装配正文在 SpringBoot 时代,经过一个main方法就能够启动一个应用,其底层依赖的就是 Spring 几个注解。从 @SpringBootApplication 注解中的 @EnableAutoConfiguration 注解开始,@EnableAutoConfiguration 属于 Spring 的 @Enable 模块注解,在该注解中经过 @Import 导入 AutoConfigurationImportSelector 类,在该类中加载全部以 AutoConfiguration 为后缀且标注 @Configuration 注解的自动配置类,每一个自动配置类能够装配一个外部模块,如 Web MVC 模块对应的配置类是 WebMvcAutoConfiguration 。在自动配置类中又有众多 @Conditional 条件注解,可达到灵活装配的目的。服务器
Spring Boot 的启动过程很是简单,只须要启动一个 main 方法,项目就能够运行,就算依赖了诸多外部模块如:MVC、Redis等,也不须要咱们进行过多的配置。
@SpringBootApplication public class LoongSpringBootApplication { public static void main(String[] args) { SpringApplication.run(LoongSpringBootApplication.class, args); } } //关注的是 @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 { @AliasFor(annotation = EnableAutoConfiguration.class) Class<?>[] exclude() default {}; @AliasFor(annotation = EnableAutoConfiguration.class) String[] excludeName() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; }
@EnableAutoConfiguration 是实现自动装配的核心注解,是用来激活自动装配的,看注解前缀咱们应该知道是Spring @Enable 模块驱动的设计模式,因此它必然会有 @Import 导入的被 @Configuration 标注的类或实现 ImportSelector 或 ImportBeanDefinitionRegistrar 接口的类。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... }
Spring Boot经过 @AutoConfigurationPackage 注解获取默认包扫描路径:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
它是经过 @Import 导入了 AutoConfigurationPackages.Registrar 类,该类实现了 ImportBeanDefinitionRegistrar 接口。
@Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { ... @Configuration @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class}) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware { ... @Bean @ConditionalOnBean(View.class) @ConditionalOnMissingBean public BeanNameViewResolver beanNameViewResolver() { ... } ... } @Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { @Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { ... } @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping() { ... } } ... }
注解部分:
装配顺序:
代码部分:
这部分就比较直接了,实例化了和 Web MVC 相关的Bean,如 HandlerAdapter、HandlerMapping、ViewResolver等。其中,出现了 DelegatingWebMvcConfiguration 类,这是 @EnableWebMvc 所 @Import导入的配置类。
能够看到,在Spring Boot 自动装配的类中,通过了一系列的 @Conditional 条件判断,而后实例化某个模块须要的Bean,且无需咱们配置任何东西。
在构造 SpringApplication 启动类时,初始化了几个重要的类,如 WebApplicationType 、ApplicationContextInitializer、ApplicationListener。其中 WebApplicationType 存储的是当前应用类型,如 Servlet Web 、Reactive Web; ApplicationContextInitializer 和 ApplicationListener 则是 SpringBoot 经过扩展 Spring 特性建立的初始化器及监听器。
SpringApplication 准备阶段结束后,按道理应该进入运行阶段,但运行阶段以前还有一个操做,就是能够修改 SpringApplication 默认配置。开头的代码示例能够看到,应用程序主类中的main方法中写的都是SpringApplication.run(xx.class),可能这种写法不知足咱们的需求,咱们能够对SpringApplication进行一些配置,例如关闭Banner,设置一些默认的属性等。下面则是利用 SpringApplicationBuilder 的方式来添加配置:
@SpringBootApplication public class DiveInSpringBootApplication { public static void main(String[] args) { new SpringApplicationBuilder(DiveInSpringBootApplication.class) // 设置当前应用类型 .web(WebApplicationType.SERVLET) // 设置 banner 横幅打印方式、有关闭、日志、控制台 .bannerMode(Banner.Mode.OFF) // 设置自定义的 banner .banner() // 追加自定义的 initializer 到集合中 .initializers() // 追加自定义的 listeners 到集合中 .listeners() .run(args); } }
使用该方式实现的SpringApplication能够对其添加自定义的配置。
四、SpringApplication启动类运行阶段在 SpringApplication 运行阶段中,先是经过扩展 Spring 监听机制,在 SpringBoot 各个阶段发布不一样事件,执行多个事件监听器;而后建立 Environment 类,这是外部化配置的核心类;最后启动 Spring 容器,经过 WebApplicationType 断定当前应用类型,建立应用对应 ApplicationContext 应用上下文,再调用 ApplicationContext#refresh 方法启动容器。
五、外部化配置之Environment外部化配置的几种资源类型,如 properties、YAML、环境变量、系统属性、启动参数等。还详细介绍了 Environment 类,该类是外部化配置核心类,全部外部化配置数据,都保存在该类中,并和你们讨论了整个存储流程。
六、外部化配置之@ConfigurationProperties@ConfigurationProperties 是 SpringBoot 实现外部化配置的重要注解,配合 SprinBoot 自动装配特性来达到快速开发的目的。主要将 properties 配置文件和 Properties 配置类中的属性进行映射,一样也和你们讨论了整个映射流程。
当 Spring Boot 集成外部组件后,就可在 properties 或 YAML 配置文件中定义组件须要的属性,如 Redis 组件:
spring.redis.url=redis://user:password@example.com:6379 spring.redis.host=localhost spring.redis.password=123456 spring.redis.port=6379
其中都是以 spring.redis 为前缀。这实际上是 Spring Boot 为每一个组件提供了对应的 Properties 配置类,并将配置文件中的属性值給映射到配置类中,并且它们有个特色,都是以 Properties 结尾,如 Redis 对应的配置类是 RedisProperties:
@ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { private String url; private String host = "localhost"; private String password; private int port = 6379; ... }
@ConfigurationProperties 的注解,它的 prefix 参数就是约定好的前缀。该注解的功能就是将配置文件中的属性和 Properties 配置类中的属性进行映射,来达到自动配置的目的。这个过程分为两步,第一步是注册 Properties 配置类,第二步是绑定配置属性,过程当中还涉及到一个注解,它就是 @EnableConfigurationProperties ,该注解是用来触发那两步操做的。
Spring Boot 外部化配置作一个总体的总结:
传统 Spring 应用需手动建立和启动 Web 容器,在 SpringBoot 中,则是嵌入式的方式自动建立和启动。SpringBoot 支持的 Web 容器类型有 Servlet Web 容器和 Reactive Web 容器,它们都有具体容器实现,Sevlet Web 对应的是 Tomcat、Jetty、Undertow,默认实现是 Tomcat;Reactive Web 对应的是 Netty 。
八、Starter机制之自定义Starter在 Spring 时代,搭建一个 Web 应用一般须要在 pom 文件中引入多个 Web 模块相关的 Maven 依赖,如 SpringMvc、Tomcat 等依赖,而 SpringBoot 则只需引入 spring-boot-starter-web 依赖便可。这就是 SpringBoot 的 Starter 特性,用来简化项目初始搭建以及开发过程,它是一个功能模块的全部 Maven 依赖集合体。
SpringBoot 提供了很是多的 Starter,下面列出经常使用的几个:
名称 | 功能 |
---|---|
spring-boot-starter-web | 支持 Web 开发,包括 Tomcat 和 spring-webmvc |
spring-boot-starter-redis | 支持 Redis 键值存储数据库,包括 spring-redis |
spring-boot-starter-test | 支持常规的测试依赖,包括 JUnit、Hamcrest、Mockito 以及 spring-test 模块 |
spring-boot-starter-aop | 支持面向切面的编程即 AOP,包括 spring-aop 和 AspectJ |
spring-boot-starter-jdbc | 支持JDBC数据库 |
spring-boot-starter-data-jpa | 支持 JPA ,包括 spring-data-jpa、spring-orm、Hibernate |