初識(shí)Spring Framework
來(lái)源:程序員人生 發(fā)布時(shí)間:2015-03-13 08:37:56 閱讀次數(shù):3399次
最近在工作用到了Spring框架,由于之前沒(méi)有接觸過(guò)Spring,就從Spring的官方文檔開始學(xué)起。在“Quick Start”介紹了1個(gè)使用Spring做依賴性注入(dependency injection)的例子,該例子使用Maven或GRADlE進(jìn)行管理的。作者之前沒(méi)有接觸過(guò)這兩個(gè)項(xiàng)目管理工具,由于時(shí)間緊急,就直接使用了Eclipse編譯了這個(gè)例子。在Eclipse下的文件結(jié)構(gòu)以下:


(由于沒(méi)有使用項(xiàng)目管理工具,剛開始只加入了spring-context.jar和spring-core.jar,又根據(jù)異常信息導(dǎo)入了commouns-logging.jar、spring-expression.jar和spring-beans.jar。這就是否是項(xiàng)目管理工具的麻煩所在。)
hello/MessageService.java的代碼以下:
package hello;
public interface MessageService {
String getMessage();
}
hello/MessagePrinter.java的代碼以下:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MessagePrinter {
final private MessageService service;
@Autowired
public MessagePrinter(MessageService service) {
this.service = service;
}
public void printMessage() {
System.out.println(this.service.getMessage());
}
}
hello/App.java的代碼以下:
package hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan
public class App {
@Bean
MessageService mockMessageService() {
return new MessageService() {
public String getMessage() {
return "Hello World!";
}
};
}
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(App.class);
MessagePrinter printer = context.getBean(MessagePrinter.class);
printer.printMessage();
}
}
編譯運(yùn)行該項(xiàng)目,會(huì)有以下輸出:


“Quick Start”最后總結(jié)說(shuō)這個(gè)充分體現(xiàn)了依賴性注入(dependency injection)的概念,至于如何體現(xiàn)的作者嘗試做1下解析,權(quán)當(dāng)對(duì)Spring Framework的1個(gè)初步認(rèn)識(shí)。
項(xiàng)目的入口是App.java的main函數(shù),在這個(gè)函數(shù)中首先聲明了1個(gè)ApplicationContext對(duì)象context,并向下轉(zhuǎn)型為AnnotationConfigApplicationContext對(duì)象。ApplicationContext是對(duì)1個(gè)利用(Application)提供配置的核心接口,AnnotationConfigApplicationContext是它的1個(gè)實(shí)現(xiàn),可用來(lái)處理用@Configuration,@Component和JSR⑶30標(biāo)注的類。由于App.java使用@Configuration進(jìn)行了標(biāo)注,故App.class可以作為AnnotationConfigApplicationContext構(gòu)造器的的參數(shù)。
MessagePrinter printer = context.getBean(MessagePrinter.class);
這句代碼通過(guò)context的getBean(Class<T>)方法得到了MessagePrinter的1個(gè)實(shí)例。為何呢得到MessagePrinter類的1個(gè)實(shí)例呢?看getBean(Class<T>)的API解釋:
Return the bean instance that uniquely matches the given object type, if any.
(如果給定的對(duì)象唯1匹配,就返回1個(gè)bean實(shí)例。)
printer.printMessage();
調(diào)用MessagePrinter的printMessage()方法,該方法以下實(shí)現(xiàn):
public void printMessage() {
System.out.println(this.service.getMessage());
}
實(shí)際上是調(diào)用了接口MessageService的getMessage()方法,由于App.java中的mockMessageService()方法中的匿名內(nèi)部類實(shí)現(xiàn)了MessageService接口,并在getMessage()方法中返回了“hello,world!”字符串,顧能在結(jié)果中輸出"hello,world!"。
使人迷惑的是在mockMessageService()方法并沒(méi)有被顯式調(diào)用,為什么其匿名內(nèi)部類能被實(shí)例化并輸出信息呢?緣由就在于程序中使用的以下Spring標(biāo)注。
@Configuration 用于標(biāo)注1個(gè)類,表示bean定義的源文件(source);
@Bean 用于標(biāo)注1個(gè)方法,表示1個(gè)方法實(shí)例化、配置或初始化1個(gè)新的對(duì)象(Object),這個(gè)對(duì)象被Spring的控制反轉(zhuǎn)(IoC)容器管理,相當(dāng)于Spring <bean />XML配置文件中<bean />元素。(詳見官方文檔)
@ComponentScan 用于標(biāo)注1個(gè)類,表示掃描指定包中的@Component標(biāo)注的類,并將這些類注冊(cè)為Spring IoC容器的bean,亦相當(dāng)于1個(gè)<bean />元素;
@Autowired 用于標(biāo)注setter方法,構(gòu)造器,包括多個(gè)參數(shù)的方法,集合等等,用于自動(dòng)綁定;
@Component 用于標(biāo)注1個(gè)類
由于MessagePrinter中有以下構(gòu)造器:
@Autowired
public MessagePrinter(MessageService service) {
this.service = service;
}
從這個(gè)構(gòu)造器中可以到MessagePrinter依賴MessgeServie,并用@Autowired標(biāo)注。這就表示在通過(guò)contexnt.getBean(MessagePrinter.class)得到MessagePrinter的1個(gè)實(shí)例時(shí),會(huì)將對(duì)MessageService的依賴自動(dòng)綁定到MessageService類,將查找所有能作為<bean />元素的類(@Component @Configuration標(biāo)注)或方法(@Bean標(biāo)注),而在App.java中有以下方法:
@Bean
MessageService mockMessageService() {
return new MessageService() {
public String getMessage() {
return "Hello World!";
}
};
}
查找到這個(gè)方法后會(huì)將這個(gè)MessageService實(shí)現(xiàn)注入到MessagePrinter實(shí)例中,從而實(shí)現(xiàn)“hello,world!”的輸出。
以上就是作者對(duì)Spring Framework文檔“Quick Start”例子的解析,有不當(dāng)?shù)牡胤?請(qǐng)多多指教。
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)