SpringBoot2

Coding挖掘機發表於2019-03-30

SpringBoot2

微服務的概念

微服務就是將一個大的系統拆分成多個子系統,然後通過REST風格的請求將他們整合起來,進一步簡化了分散式系統的開發

SpringBoot2的特點

  • 約定大於配置,通過引入xx-starter加上自定義的配置檔案就可以整合某個元件的java客戶端
  • 內建tomcat/undertow
  • 提供快速的測試環境

為什麼要學這個

每天都在用SpringBoot缺不知道其中的原理,典型的日用而不知。一旦出現開發的問題,就是一頓部落格亂找,很久也解決不了問題 所以,理解原理很重要

Bean的宣告週期

1.Spring通過配置,如@SpringBootApplication或@ComponentScan定義的路徑(預設為當前包和子包)找到帶有@Component的類

2.解析類定義,把Bean定義釋出到Ioc容器中,注意:是定義,不是例項

3.Ioc容器裝載Bean的定義

4.建立Bean的例項物件

5.開始掃描@Autowired注入各類資源

踩坑

@Service
public class Service{
    @Autowired
    public String kafkaHost;
    
    public KafkaAppender;
    public Service(){
        KafkaAppender = new KafkaAppender(kafkaHost);
    }
}
複製程式碼

注意,當Service被初始化時,會呼叫構造器,此時kafkaHost還沒被Autowired注入,所以這個時候kafkaHost為null

Spring註解說明

Spring註解之Bean註解:

@Configuration
public class AppConfig {
    @Bean(name="user"} 
    public User initUser () {
        User user= new User (); 
        user.setId(100) ;
        user.setUserName();
        return user;
    }
}

@Service    
public class System{
    @Autowired
    private User user;
}   
複製程式碼

@Bean表示將initUser返回的user裝配到Ioc中,而且該bean的name為user。如果沒有定義name,則bean的name為方法名(initUser)

@ComponentScan與@Component

@Component("user")
public class User {
    private id; 
    private String userName; 
    private String note;
}

@Service    
public class System{
    @Autowired
    private User user;
}    
複製程式碼

注意事項

  • @Component註解作用域預設為singleton
  • @Component表名這個類將被Ioc裝配,而且該bean的name為user,如果沒有顯示定義name,則以類名第一個字母小寫作為bean的name
  • @Component使用在不確定哪一個層的時候使用,可以作用在任何層次,把普通pojo例項化到spring容器
  • 不推薦使用@Component註解,而應該使用它的擴充套件,如@Service、@Repository

業務元件的註釋

  • @Component 沒有明確角色的元件
  • @Service 在業務邏輯層(Service層)使用
  • @Repository 在資料訪問層(dao層)使用
  • @Controller 用於標註控制層元件
  • @RestController 純REST風格的控制器
@Service
@Service註解作用在類上
@Service註解作用域預設為singleton
使用註解配置和類路徑掃描時,被@Service註解標註的類會被Spring掃描並註冊為Bean
@Service註解用於標註業務的邏輯元件,即服務元件元件
複製程式碼
@Repository
@Repository註解作用在類上
@Repository註解作用域預設為singleton
使用註解配置和類路徑掃描時,被@Repository註解標註的類會被Spring掃描並註冊為Bean
@Repository註解用於標註資料訪問元件,即DAO元件
@Repository註解的作用不只是將類識別為Bean,同時它還能將所標註的類中丟擲的資料訪問異常封裝為 Spring 的資料訪問異常型別
複製程式碼

@Controller

@Controller註解作用在類上
使用註解配置和類路徑掃描時,被@Controller註解標註的類會被Spring掃描並註冊為Bean
@Controller用於標註Web中控制層元件
被@Controller標註的類負責處理由DispatcherServlet分發的請求,
它把使用者請求的資料經過業務處理層處理之後封裝成一個Model ,然後再把該Model返回給對應的View進行展示
@Controller和@RequestMapping、@RequestParam等一些註解共同處理URL的對映
複製程式碼

@ComponentScan意味著掃描當前註釋類所在的包和子包

@SpringBootApplication

@SpringBootApplication預設包含了@ComponentScan

@Autowired、@Primary、@Qualifier

Spring最常用的註解,根據型別找到對應的Bean進行注入,也就是getBeanByType()

  • 首先根據型別找到對應型別的Bean,如果不唯一,則按照Bean名稱進行匹配,如果還找不到,就拋異常
  • 當對應型別的Bean有多個時,@Primary告訴Ioc容器,優先使用帶有@Primary標識的Bean
public interface User {
}
@Component
@Primary
public class Man implements {
}
@Component
public class Woman implements {
}

public class System{
    @Autowired
    private User user;
    這裡裝配的是Woman
}
複製程式碼
  • @Qualifier告訴Ioc容器按照型別和名稱去找到對應的Bean
public interface User {
}
@Component
@Primary
public class Man implements {
}
@Component
@Primary
public class Woman implements {
}

public class System{
    @Autowired
    @Qualiefier("man")
    private User user;
    這裡裝配的是Man
    
    public void heiheihei(@Autowired @Qualiefier("man") User user){};
}
複製程式碼

@Value與@ConfigurationProperties

從配置檔案中獲取屬性

@Component
@ConfigurationProperties(prefix = "microservice.quickstart")
public class User{
    @Value('${user.name}')
    private String userName;
    //讀取配置檔案中的microservice.quickstart.user.name配置
}

複製程式碼

多環境配置下的啟動

按照工程建立

  • application.properties
  • application-dev.properties
  • application-test.properties
  • application-prd.properties 啟動時新增命令作為引數 java -jar xx.jar -Dpsirng.profiles.active=dev java -jar xx.jar -Dpsirng.profiles.active=test java -jar xx.jar -Dpsirng.profiles.active=prd

@Scope作用在類上和方法上

@Scope用來配置Bean的作用域,有以下幾種

singleton單例模式

Spring 容器中有且只有一個Bean例項,只要Spring容器不銷燬或退出,該Bean例項就會一直存活

prototype原型模式

每次獲取Bean的時候會有一個新的例項,Spring容器不能對返回Bean例項的整個生命週期負責

request模式

request只適用於Web程式,每一次HTTP請求都會產生一個新的bean, 同時該bean僅在當前HTTP request內有效,當請求結束後,該物件的生命週期即告結束

session模式

session只適用於Web程式,session作用域表示該針對每一次HTTP請求都會產生一個新的bean, 同時該bean僅在當前HTTP session內有效

application模式

application只適用於Web程式,全域性作用域

@Conditional(TestCondition.class)

這句程式碼可以標註在類上面,表示該類下面的所有@Bean都會啟用配置,也可以標註在方法上面,只是對該方法啟用配置。

@ConditionalOnBean(僅僅在當前上下文中存在某個物件時,才會例項化一個Bean) @ConditionalOnClass(某個class位於類路徑上,才會例項化一個Bean) @ConditionalOnExpression(當表示式為true的時候,才會例項化一個Bean) @ConditionalOnMissingBean(僅僅在當前上下文中不存在某個物件時,才會例項化一個Bean) @ConditionalOnMissingClass(某個class類路徑上不存在的時候,才會例項化一個Bean) @ConditionalOnNotWebApplication(不是web應用)

spring原始碼閱讀

@EnableWebMvc、WebMvcConfigurationSupport和WebMvcConfigurationAdapter三者之間的區別是什麼 @EnableWebMvc註解的類等於extends WebMvcConfigurationSupport 但是沒有重寫任何方法 SpringBoot WebMVC的自動配置資訊都在WebMvcAutoConfiguration這個類中,我們看他的原始碼

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638) //Bean的初始化順序
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
複製程式碼

其中@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})的意思是,當工程中沒有WebMvcConfigurationSupport 時,才會使用WebMvc的自動配置;我們一般會繼承WebMvcConfigurationSupport來自定義配置類, 但是一旦繼承WebMvcConfigurationSupport後就會出現新的問題: 會發現Spring Boot的WebMvc自動配置失效,具體表現比如訪問不到靜態資源(js,css等)了。

攔截器原理

動態代理

上海體育公園有很多大爺大媽相親,你要去尋找女朋友。這時,你就問大媽:女兒喜歡什麼呀,大媽可能會替她回答。 當然,大媽覺得你髮際線太高,他也可以直接拒絕。這時,這個大媽就是她女兒的代理

JDK中的使用方式

JDK提供了類Proxy的靜態方法:newProxyInstance.

public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException

這裡的invocationHandler是一個介面InvocationHandler物件,定義了invoke方法,這個方法就是實現代理物件邏輯的 通過target\method\args就能夠用反射方法執行了

具體見:ProxyBean.java[請學會用IDEA找到對應名字的類]

AOP約定流程

按照我們上面實現的程式碼,可以看到,AOP是一種規範化的約定,我們按照這種約定來使用,就可以實現動態代理 aop-principle.png

SpringBoot2

攔截器使用AOP的約定

spring-intercetor.png

SpringBoot2

Spring中使用@AspectJ

Spring AOP使用@AspectJ對方法進行攔截,所以,我們要先確定什麼地方需要AOP,也就是連線點 有了連線點後,我們需要一個切面,用來描述流程的織入 請看案例:

MyAspect.java

Myabits中的資料庫事務

@Transactional可以放在方法上,也可以放在類上 如果放在類上,則該類的所有方法都預設帶了@Transactional 案例請檢視

com.liuyiling.microservice.api.controller.DataBaseController.transactional

注意事項

  • @Transactional必須加在public方法上,否則CGlib代理會找不到
  • 正確的設定@Transactional 的 isolation 屬性

事務的隔離度,預設值採用 DEFAULT

  • 事務必須註解在非自呼叫方法上,下面面這個例子事務將不會被呼叫
@Service
public class OrderService {
    private void insert() {
        insertOrder();
    }
    
    @Transactional
    public void insertOrder() {
    }
}
複製程式碼
  • 可以指定事務的回滾條件

預設情況下,如果在事務中丟擲了未檢查異常(繼承自 RuntimeException 的異常)或者 Error,則 Spring 將回滾事務;除此之外,Spring 不會回滾事務。 如果在事務中丟擲其他型別的異常,並期望 Spring 能夠回滾事務,可以指定 rollbackFor。例: @Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class)

相關文章