知識(shí)儲(chǔ)備
- spring有兩個(gè)很大的特點(diǎn):面向切面編程(AOP)和依賴注入(DI),現(xiàn)在只了解DI簡(jiǎn)單介紹DI
- 應(yīng)用場(chǎng)景:類A的某個(gè)屬性是B類對(duì)象浅碾,這種情況實(shí)例化類的時(shí)候必須要?jiǎng)?chuàng)建這個(gè)B對(duì)象,也就意味著需要向A類中引入另一個(gè)類B
import B;
class A {
private B b;
public A(){
b= new B()
}
}
---->使用上述方式缺點(diǎn)明顯在于:
- AB耦合度很高
- 并且對(duì)A做單元測(cè)試的時(shí)候穴翩,沒有辦法mock B
- 因此DI引入邀窃。
DI簡(jiǎn)單理解
- 依賴注入是什么:創(chuàng)建一個(gè)需要依賴其他類B的對(duì)象A荸哟,DI會(huì)將A依賴的B給,而不是讓A自己去獲取
- DI實(shí)際功能:DI幫助我們創(chuàng)建了對(duì)象并且管理依賴關(guān)系瞬捕。當(dāng)我們將類的創(chuàng)建和裝配交給別的類管理時(shí)候鞍历,我們只需要簡(jiǎn)單的使用例如@Inject@Autowired這些注解直接注入對(duì)象即可。
- 如何實(shí)現(xiàn)DI:XML或者創(chuàng)建ApplicationContext類(這個(gè)后面會(huì)詳細(xì)解析)
- DI
- 但是上一條的前提是要求我們的類比如A使用構(gòu)造器注入方式
class A {
private B b;
public A(B b){
this.b = b;
}
}
- 裝配:創(chuàng)建應(yīng)用組件之間協(xié)作的行為(比如我要?jiǎng)?chuàng)建一個(gè)A的bean但是我需要B那么創(chuàng)建A的Bean的過(guò)程就是裝配)
注意點(diǎn):使用IDEA+gradle當(dāng)你引入新的depend的時(shí)候要點(diǎn)擊下方的import否則包不會(huì)引入--->也就等同于如果不npm install 那么就不會(huì)引入庫(kù)
spring的配置
- 作用:1.告訴spring那些類需要Bean2.告訴spring針對(duì)那些有依賴的類肪虎,如何創(chuàng)建他的Bean
- 方式:1.使用xml文件配置 2. 使用javaConfig類配置 3.隱式的bean發(fā)現(xiàn)機(jī)制和自動(dòng)賺
一: spring的自動(dòng)化配置
自動(dòng)化配置分成兩個(gè)方向:
- 1.組件掃描:掃描就是找到需要?jiǎng)?chuàng)建Bean的類并且將Bean創(chuàng)建好放入到spring的上下文
- 2.自動(dòng)裝配:類似于上文中的A類bean的創(chuàng)建需要依賴B的bean這時(shí)候創(chuàng)建A的Bean將B的bean注入A就是自動(dòng)裝配
自動(dòng)化掃描
- what:就是通過(guò)為類添加注解劣砍,告訴spring那些類需要?jiǎng)?chuàng)建Bean
- how:1.為需要bean的類添加@Component/@Service/@等注解,作用是告訴spring這些類是需要?jiǎng)?chuàng)建Bean的(類似于在某個(gè)方法上添加@Bean注解)扇救。 2.添加configuration類:作用是告訴spring去找類似于@Component這類創(chuàng)建Bean
3.簡(jiǎn)單的在你的運(yùn)行類中加載spring的時(shí)候讓他去執(zhí)行configuration類即可 - example:https://github.com/iepgnahz/auto-configuration.git commitId 2f6775f2660787fcfacc6e8c62032bbead5f7e25
自動(dòng)化掃描中遇到的bug
- Q1:我想通過(guò)測(cè)試自動(dòng)注入的cd是否存在刑枝,來(lái)確定我們使用的@Component和@ComponentScan是否可以spring創(chuàng)建CD的bean香嗓,但是測(cè)試中我只添加了@Runwith注解立刻就爆出沒辦法創(chuàng)建Test bean,為什么装畅?
- A1:雖然我們創(chuàng)建了config類靠娱,但是在運(yùn)行測(cè)試的時(shí)候并沒有讓測(cè)試執(zhí)行config類,因此洁灵,我們需要在運(yùn)行類的定義處添加注解@ContextConfiguration提醒運(yùn)行類執(zhí)行config類
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
//@SpringBootTest //你會(huì)發(fā)現(xiàn)使用這個(gè)注解不需要上面那個(gè)注解也可以成功運(yùn)行饱岸,我認(rèn)為是這個(gè)注解自動(dòng)去掃描了@Component類并且為你創(chuàng)建了Bean
public class AutoConfigApplicationTests {
@Autowired
private CompactDisc cd;
@Test
public void play_should_print_CD_info() throws Exception {
assertThat(cd).isNotNull();
} //這測(cè)試僅僅是用來(lái)確定cd 可以自動(dòng)掃描并創(chuàng)建bean(僅僅使用兩個(gè)注解)
}
- Q2:為什么當(dāng)我們只添加上面代碼中的@SpringBootTest就可以運(yùn)行成功?
- A2:我猜測(cè)是springBoot自動(dòng)幫我們創(chuàng)建了Config類并讓spring執(zhí)行徽千,找到所有帶有@Component@Service等的類并未他們創(chuàng)建Bean
自動(dòng)化裝配
- why/what:某個(gè)類A其中有個(gè)屬性是B對(duì)象苫费,當(dāng)創(chuàng)建A的bean的時(shí)候需要到spring上下文中找B的bean才能創(chuàng)建成功,希望B的bean可以自動(dòng)注入A的Bean中就是自動(dòng)化裝配
- how:使用@Autowired注解自動(dòng)注入B入A
class A{
private B b;
@Autowired
public A(B b){
this.b =b
} //這是構(gòu)造方法注入双抽,推薦使用這種方式百框,這樣可以方便的對(duì)A做單元測(cè)試,因?yàn)榭梢栽谑褂肁的構(gòu)造方法同時(shí)注入一個(gè)mock的B bean
}
class A{
@Autowired
private B b;
//這是直接注入
}
@Autowired可以用在屬性的聲明之前還可以用在各種帶有Bean參數(shù)的方法前牍汹,諸如構(gòu)造方法铐维,setB方法,但是要求參數(shù)必須是可以注入的Bean
- example:https://github.com/iepgnahz/auto-configuration/ commitId cf0352aa5bfef4ccc4f62eb8967cc055dcca1704
自動(dòng)化裝配demo中遇到的bug
- Q1:想要對(duì)CDplayer類做一個(gè)單元測(cè)試慎菲,因此需要Mock掉使用的CompactDisc的對(duì)象測(cè)試CDPlayer的playCD方法嫁蛇,然而playCD是一個(gè)沒有返回值的方法,那我該如何測(cè)試呢露该?并且其中調(diào)用了CompactDisc的play方法也是沒有返回值的睬棚,那么該如何mock?
- A1:針對(duì)沒有返回值函數(shù)的測(cè)試解幼,我們使用verify測(cè)試一下函數(shù)是否被調(diào)用即可抑党。
- Q2:那么verify該如何使用呢?
- A2:verify可以用來(lái)測(cè)試某一個(gè)被mock的對(duì)象中的方法是否被調(diào)用或者調(diào)用幾次或者使用什么參數(shù)調(diào)用撵摆,但是注意:verify的第一個(gè)參數(shù)就是那個(gè)被mock的對(duì)象底靠,并且verify只能檢測(cè)被mock掉的對(duì)象中方法的調(diào)用情況,沒有被mock的對(duì)象沒辦法測(cè)試
- Q3.無(wú)法確定veriy能夠處理的對(duì)象有哪些呢特铝?因?yàn)槲矣浀迷趎odejs中只有把對(duì)象spy了才能夠監(jiān)測(cè)他暑中,在java中不需要嗎?
- A3:verify既可以處理Mock的對(duì)象也可以處理spy對(duì)象