spring boot自動化配置原理

spring-cloud其他文章:
我們有必要花時間瞭解spring boot嗎?
spring boot集成ActiveMQ
spring-cloud中eureka進行服務治理

概述

spring boot系列(第一篇):我們有必要花時間瞭解spring boot嗎?

spring boot好用,原因在於省去了很多繁雜的配置。一般開發服務端項目需要的服務、數據庫、事務、緩存、消息、作業、訪問控制,這些模塊的基礎配置,spring boot都給我們配置好了。

需要哪個模塊,我們要做可能就是簡單的幾項操作:添加對應的starter依賴;在application.properties文件添加url、端口、線程數、隊列名稱等屬性值;添加@Enablexxx註解。

spring boot流行的原因也是在於它的簡單、快速,恰好貼合了當前主流的敏捷、快速迭代的需求,給微服務化帶來了很多便利。

spring boot的優點不僅僅是自動化配置,還有它的actuator提供的生產環境運維支持,打包成單個jar支持,上雲支持。這些內置的支持,讓java服務開發變得簡單、快速、專業、易於維護。

註解orXML?

spring boot官方是主張完全用註解替代XML的。那麼實際生產環境下,我們該用註解還是該用XML,哪裏用註解,哪裏用XML?

在stackoverflow上有一個討論,可以看這裏.

大意是說,應該結合使用annotation和XML,但遇到依賴注入的類時,被依賴的對象應該使用XML配置。這樣,當需要修改實現類的時候,能夠不修改代碼、不重新打包完成更換。

對於生產環境,一般來說很少直接線上切換不同的實現類,換也是線下隨着某一個版本的發佈,完成替換。

有一點需要注意的是,對於上述提到的被依賴接口的實現類最好在單獨的位置去註解,不要直接在類上註解@Component、@Repositry、@Service。建議,當一個類的實例被其他類依賴時,在一個@Configuration註解的類裏面,用@Bean去註解需要實例化的類,@Configuration和@Bean是spring 3.0之後開始支持的一組新註解,從而可以支持完全無XML配置。如下形式:

package com.dangdang.cart_test.configuration.web;

import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebConfiguration {

    @Bean
    public RemoteIpFilter remoteIpFilter() {
        return new RemoteIpFilter();
    }

    @Bean
    public IBookService bookService(){
        return new MyBookService();
    }

}

而不要直接在實現類上註解,不要像這樣:

package com.dangdang.cart_test.configuration.web;

import org.springframework.stereotype.Service;

@Service
public class MyBookService implements IBookService{

}

相對於spring來說,spring boot要年輕不少。現實情況下,公司的項目很多配置都是XML配置的,這時候估計絕大多數人不會想着全部改成Annotation配置的。

對於這種情況,可以沿用XML配置,也可以對新的類用Annotation註解。Annotation和XML同時存在。

spring boot的自動註解做了什麼

spring mvc項目最基礎的配置需要

看一下常規的spring mvc 項目,需要web.xml配置DispatcherServlet、CharacterEncodingFilter、ContextLoaderListener:

    <!-- 指定bean 容器上下文配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/**/*.xml,classpath:*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 編碼過濾器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Spring MVC 前端控制器 -->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/appconfig/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>  

還需要在spring mvc上下文配置文件中,配置MethodHandler、ViewResolver:

    <!-- 定義跳轉的文件的前後綴 ,視圖模式配置 -->
    <bean   class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 這裏的配置我的理解是自動給後面action的方法return的字符串加上前綴和後綴,變成一個 可用的url地址 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

spring boot mvc項目配置需要

pom.xml引入starter-web的jar包:

        <dependency>
                    <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

application.properties中配置viewresolver的屬性:

spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

spring boot做了什麼

1.自動創建常規的配置項DispatcherServlet、CharacterEncodingFilter、ContextLoaderListener、viewresolver;

2.需要配置的屬性,統一在properties文件裏面以spring.mvc.xxx格式的屬性名配置;

自動註解實現

spring boot爲每一個支持的技術(quartz、cache、batch、activemq)都提供了一個starter。引入的一個starter,就對應的引入了這項技術依賴的所有jar文件。

1.比如quzrtz的starter:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
    </dependencies>

2.每一個技術還對應了一個autoconfigure,用來當滿足某個條件時(一般是某個類存在 && 某個對象不存在),自動實例化需要的對象,比如:

@Configuration
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class,
        PlatformTransactionManager.class })
@EnableConfigurationProperties(QuartzProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class })
public class QuartzAutoConfiguration {
    //省略細節的初始化代碼
}

這裏的@ConditionalOnClass,指定當Scheduler.class, SchedulerFactoryBean.class,PlatformTransactionManager.class (都是quartz的初始化需要的類)都存在時,執行初始化。

@AutoConfigureAfter指定,如果存在DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class配置的話,先執行他們內部的配置代碼。

定義一個自動註解

定義一個自定義註解,和spring boot提供的註解一般會有一個小的差別,就是自定義starter的pom.xml會引入自定義的configure項目,這樣使用的時候,就可以少引入一個dependency了。或者乾脆放到一個autoconfigure工程裏面。

github上有一個比較完整、詳細的實例,可以參見

備註參考:

spirng boot autoconfigure-徐敏博客:https://my.oschina.net/smartsales/blog/775550
自定義自動配置–github示例項目:https://github.com/snicoll-demos/spring-boot-master-auto-configuration
@Configuration如何使用–官方javadoc(比任何博文都全面完整):https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html
maven pom文件中的optional作用:http://blog.csdn.net/ado1986/article/details/39547839
@configuration無法注入的一個問題(建議不要像文章那樣,而是最好使用@PropertySource):http://www.coderli.com/spring-configuration-autowire-failed/

發佈了141 篇原創文章 · 獲贊 140 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章