Spring Boot的特性
1)、創建獨立的Spring應用
2)、直接嵌入Tomcat、Jetty或Undertow等Web容器(不需要部署WAR文件)
3)、提供固化的starter依賴,簡化構建配置和依賴管理
4)、當條件滿足時自動地裝配Spring或第三方類庫
5)、提供運維(Production-Ready)特性,如指標信息(Metrics)、健康檢查及外部化配置
6)、絕無代碼生成,並且不需要XML配置
即約定大於配置,簡化開發。
為什么說是獨立的Spring應用?
SpringBoot應用無需再向傳統的JavaEE應用那樣,將應用打包成WAR文件或者JAR文件,並部署到JavaEE容器中運行(雖然其也支持)。
SpringBoot應用采用嵌入式Web容器,獨立於外部容器,對應用生命周期擁有完全自主的控制。
在傳統的Spring應用中,外置容器需要啟動腳本將其引導(如ContextLoaderListener),隨其生命周期回調執行Spring上下文的初始化。比較代表性的是Spring Web中的
ContextLoaderListener和Web MVC中的DispatcherServlet,前者利用ServletContext生命周期構建Web ROOT Spring應用上下文,后者結合Servlet生命周期創建DispatcherServlet
的Spring應用上下文。無論何種方式,均屬於被動的回調執行,這也是為什么它們沒有完整的應用主導權的原因。
當Spring Boot出現嵌入式容器啟動方式后,嵌入式容器則稱為應用的一部分,從本質上來說,它屬於Spring應用上下文的組件Beans,這些組件和其他組件均由自動裝配
特性Spring Bean定義(BeanDefinition),隨Spring應用上下文啟動而注冊並初始化。而驅動Spring應用上下文啟動的核心組件則是Spring Boot核心API SpringApplication,
所以是Spring應用,也可以稱為SpringBoot應用。
理解自動裝配
SpringBoot引導類:
//@ImportResource 導入xml配置文件
@SpringBootApplication public class SpboApplication { public static void main(String[] args) { SpringApplication.run(SpboApplication.class, args); } }
@SpringBootApplication注解:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Configuration @EnableAutoConfiguration @ComponentScan //SpringBoot會自動掃描當前類的同級包以及下級包里的Bean,並自動注入到Spring容器中 public @interface SpringBootApplication { /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<?>[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default {}; /** * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses} * for a type-safe alternative to String-based package names. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; /** * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to * scan for annotated components. The package of each class specified will be scanned. * <p> * Consider creating a special no-op marker class or interface in each package that * serves no purpose other than being referenced by this attribute. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; }
可以看到@SpringBootApplication注解是一個組合注解
相當於@Configuration、@EnableAutoConfiguration、@ComponentScan的累加
@EnableAutoConfiguration:激活Spring Boot自動裝配機制
@ComponentScan:激活@Component的掃描
@Configuration:聲明被標注為注解類
同時,其屬性方法帶有@AliasFor注解,用於橋接其他注解的屬性。
@EnableAutoConfiguration注解可以幫我們自動載入應用程序所需要的所有默認配置
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<?>[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default {}; }
此注解有兩個重要的注解:
@Import:向Spring容器中導入了EnableAutoConfigurationImportSelector組件
@AutoConfigurationPackage:自動配置包
1):@AutoConfigurationPackage:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
發現還是依靠Import注解導入了AutoConfigurationPackages.Registrar組件,其代碼為:
/** * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing * configuration. */ @Order(Ordered.HIGHEST_PRECEDENCE) static class Registrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, ClassUtils.getPackageName(metadata.getClassName())); } }
其作用是將主配置類(@SpringBootApplication)的所在包及其子包里面的組件掃描到Spring容器中。比如帶有@Entity注解的組件,由
@AutoConfigurationPackage掃描並加載,而平時常用的@Controller/@Service/@Component/@Repository這些注解是由ComponentScan
來掃描並加載的。
2):EnableAutoConfigurationImportSelector組件
會在Spring啟動的時候掃描所有jar路徑下的META-INF/Spring.factories,然后篩選出以EnableAutoConfiguration為key的數據,加載到IOC
容器中,最后會默認加載113個默認的配置類,實現自動配置功能。
理解約定大於配置
即通過約定來減少配置。約定優於配置是一個簡單的概念。系統、類庫、框架應該假定合理的默認值,而非要求提供不必要的配置。
大部分情況下,使用框架提供的默認值會讓你的項目開發起來效率更快。如:
在Spring Boot中,當我們導入一個spring-boot-starter-web后。就會自動地幫我們導入Spring MVC的相關依賴(包括Json支持的Jackson和數據校驗的HibernateValidator)
和一個內置的Tomcat容器,這使得開發階段可以直接通過main方法或者JAR包獨立運行一個WEB項目。因為Spring Boot約定,當你導入了一個spring-boot-starter-web后,
就約定了你是一個web開發環境。
獲取屬性配置文件的Properties
在常規的Spring環境下,注入properties文件里的值要通過@PropertySource指明properties文件的位置,然后通過@Value注入值,在SpringBoot里,只需要在application.properties
定義屬性,直接使用@Value注入即可。但是如果我們的配置比較多的話,則@Value會注入很多次。所以SpringBoot還提供了基於類型安全的配置方式,通過@Configurationproperties
將properties屬性和一個Bean及其屬性關聯,從而實現類型安全的配置。
// 將前綴為self的屬性配置和bean關聯起來,使用時直接依賴注入此bean即可 @Component @ConfigurationProperties(prefix = "self") public class SelfProperties { private String name; private Long age; get set... }