這一篇在前一篇Springmvc的基礎上,加上Spring。Spring的主要用途叫做控制反轉(依賴注入,IoC/DI)和面向切面的編程(AOP),本文只介紹IoC,因為AOP主要的應用場景是記錄日志,暫時不需要,等我要整合的幾個框架都整合在一起的時候再加上。
pom.xml不需要新添加任何東西,因為spring-core等包都在導入spring-webmvc的時候作為依賴項被導入了,所以直接來看配置。
1. web.xml
Spring要在程序需要某個對象的時候,把這個對象的實例注入進去,默認情況下,Spring以單例的形式維護了所有需要注入的對象的實例,哪里需要就把對應的實例給哪里,Spring自己對實例、程序運行的管理構成了Spring自己的容器,第一步就是要在web.xml中注冊,初始化這個容器:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/META-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
這里注冊一個ContextLoaderListener,並指定spring配置文件的位置,在類路徑下的/META-INF/applicationContext.xml,現在在maven的resources資源包下,即src/main/resources下面創建目錄META-INF,在這個目錄下創建applicationContext.xml,這個文件就是spring的配置文件。
2. applicationContext.xml
applicationContext.xml是spring的核心配置文件,spring4和之前版本的一個很大的區別,就是推薦情況下bean不是在xml文件中配置,而是通過掃描固定annotation的類,根據對象的類型或者名字自動加載,以前在applicationContext.xml需要配置大量的bean,現在不用了,但是仍然要告訴spring,去哪個包下面找這些帶着annotation等着被掃描的類:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> <context:component-scan base-package="org.zhangfc.demo4ss.service"/> </beans>
前面這一堆東西先不用管,直接粘貼好了,其實很多現在還用不到,不過也沒有關系,先放在這好了,真正有用的配置就一句話,需要spring管理的類,請到org.zhangfc.demo4ss.service下面去找。
3. UserService.java
下面寫一個服務類,用來獲得注冊用戶列表,創建package:org.zhangfc.demo4ss.service,在下面創建接口UserService,寫一個方法獲取所有用戶名。
public interface UserService { public List<String> getAllUsernames(); }
再創建一個類UserServiceImpl,實現這個接口:
@Service public class UserServiceImpl implements UserService { public List<String> getAllUsernames() { List<String> users = new ArrayList<String>(); users.add("zhangsan"); users.add("lisi"); users.add("wangwu"); return users; } }
這里比較關鍵的就是@Service這個annotation,它告訴Spring,我是一個Service,需要你來管理我。
4. HomeController
回到控制器里,上一篇文章我寫了一個方法叫json來返回一個json對象,現在改一下這個方法,通過前面寫的UserService來獲取用戶列表並返回給客戶端。
首先定義一個類的全局變量UserService:
@Autowired private UserService userService;
這里要注意的是Autowire這個annotation,它是為了告訴spring,這個對象沒有實例化,需要你來注入一個UserService的實例,那問題就是,UserSerivce是一個接口,不指定誰知道你想用的實現類是哪個,Spring會首先看自己的容器里有沒有一個叫做userService的對象(剛才那個UserServiceImpl的對象名字就叫做userServiceImpl),如果找不到就在配置文件里配置的路徑下面尋找UserService的實現類,找到了就把它的對象拿過來,除此之外剛才Service那個annotation還可以指定一個value:
@Service("userService")
這樣一來,對於UserServiceImpl這個類的實例,Spring給它起的名字就不是userServiceImpl了,而是userService,如果某個接口的實現類有多個,就可以使用這種方法來指定用哪個實現類,個人認為,如果每個接口都只有一個實現類,那么這么做確實很方便,但如果有多個實現類並且可能會更換的話,就不如配置文件明了了(當然了,現在這種方式也可以把參數抽出來放到配置文件里,不過還是麻煩一些)。
然后修改json方法:
@RequestMapping("/json") @ResponseBody public List<String> json(){ return userService.getAllUsernames(); }
Spring在這里的作用就是把HomeController需要的userService注入進來,運行程序,訪問http://localhost:8080/demo4springmvc-spring/json:
["zhangsan","lisi","wangwu"]
Spring的另一個功能AOP暫且不用,等需要記錄日志的時候再寫,當然,Spring本身也有很多復雜的機制,后面在具體問題中慢慢介紹。