SpringBoot編程思想


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...
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM