一.spring的核心模塊css
Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在覈心容器之上,核心容器定義了建立、配置和管理 bean 的方式,組成 Spring 框架的每一個模塊(或組件)均可以單獨存在,或者與其餘一個或多個模塊聯合實現。每一個模塊的功能以下:前端
1)Spring Core:核心容器,BeanFactory提供了組件生命週期的管理,組件的建立,裝配,銷燬等功能java
SpringContext:ApplicationContext,擴展核心容器,提供事件處理、國際化等功能。它提供了一些企業級服務的功能,提供了JNDI,EJB,RMI的支持。程序員
2) Spring AOP:提供切面支持web
3) Spring DAO:提供事務支持,JDBC,DAO支持spring
4) Spring ORM:對流行的O/R Mapping封裝或支持數據庫
5) Spring Web:提供Web應用上下文,對Web開發提供功能上的支持,如請求,表單,異常等。express
6) Spring Web MVC:全功能MVC框架,做用等同於Struts。apache
7)核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉 (IOC)模式將應用程序的配置和依賴性規範與實際的應用程序代碼分開。編程
二.IOC的概念
控制反轉(IOC):是面向對象編程中的一種設計原則,用來下降程序代碼之間的耦合度,
使整個程序體系結構更加靈活,與此同時將類的建立和依賴關係寫在配置文件裏,由配置文件注入,達到鬆耦合的效果。
與此同時IOC也稱爲DI(依賴注入),依賴注入是一種開發模式;依賴注入提倡使用接口編程;
依賴注入使得能夠開發各個組件,而後根據組件之間的依賴關係注入組裝。
spring的注入方式:
(1) 基於特定接口(侵入式方案)
(2) 基於set方法:是容器經過調用無參構造器或無參static 工廠方法實列化bean以後,調用該bean的setter方法, 即實現了基於setter的依賴注入
(3) 基於構造器:主要採用構造函數和構造器來進行注入
2.3.Spring容器
Spring容器負責生成、組裝、銷燬組件,並負責事件處理、國際化等功能。
(1) BeanFactory<interface>
① 核心容器,負責組件生成和裝配
② 實現主要包括Xml BeanFactory
(2) ApplicationContext
(3) WebApplicationContext
(4) ……
Resource:interface,用來包裝資源
xmlBeanFactory:BeanFactory的一個實現,使用Resource對象來查找配置文件
BeanFactory.gerBean(「BeanId」):取得以參數命名,或者Id等於參數值的一個Bean實例。
BeanFactory(容器)在默認狀況下,會採用單例方式返回對象。容器只到調用getBean方法時,纔會實例化某個對象。
(1) Spring能夠採用XML或者.properties文件做配置
(2) 配置文件(XML)
根元素能夠有多個子元素,每一個表明一個須要裝配的對象。
public class HelloServiceTest { @Test public void testHelloWorld() { // 一、讀取配置文件實例化一個IOC容器 ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml"); // 二、從容器中獲取Bean,注意此處徹底「面向接口編程,而不是面向實現」 HelloService helloService = context.getBean("helloService", HelloService.class); // 三、執行業務邏輯 helloService.sayHello(); } }
3、AOP核心概念
一、Aspect(切面)
切面,是對交叉業務邏輯的統稱。
二、Joinpoint(鏈接點)
鏈接點,指切面能夠織入到目標對象的位置(方法,屬性等)。
三、Advice(通知)
通知,指切面的具體實現。
四、Pointcut(切入點)
切入點,指通知應用到哪些類的哪些方法或屬性之上的規則。
五、Introduction(引入)
引入,指動態地給一個對象增長方法或屬性的一種特殊的通知。
六、Weaving(織入)
織入,指將通知插入到目標對象。
七、Target(目標對象)
目標對象,指須要織入切面的對象。
八、Proxy(代理對象)
代理對象,指切面織入目標對象以後造成的對象。
3.1.AOP的原理
Spring AOP採用動態代理的過程:
(1) 將切面使用動態代理的方式動態織入到目標對象(被代理類),造成一個代理對象;
(2) 目標對象若是沒有實現代理接口,那麼Spring會採用CGLib來生成代理對象,該代理對象是目標對象的子類;
(3) 目標對象若是是final類,而且也沒實現代理接口,就不能運用AOP。
AOP編程實際上是很簡單的事情,縱觀AOP編程,程序員只須要參與三個部分:
一、定義普通業務組件
二、定義切入點,一個切入點可能橫切多個業務組件
三、定義加強處理,加強處理就是在AOP框架爲普通業務組件織入的處理動做
因此進行AOP編程的關鍵就是定義切入點和定義加強處理,一旦定義了合適的切入點和加強處理,AOP框架將自動生成AOP代理,即:代理對象的方法=加強處理+被代理對象的方法。
基於Spring的AOP簡單實現
注意一下,在講解以前,說明一點:使用Spring AOP,要成功運行起代碼,只用Spring提供給開發者的jar包是不夠的,請額外上網下載兩個jar包:
一、aopalliance.jar
二、aspectjweaver.jar
先定義一個接口:
public interface HelloWorld { void printHelloWorld(); void doPrint(); }
定義兩個接口實現類:
public class HelloWorldImpl1 implements HelloWorld { public void printHelloWorld() { System.out.println("Enter HelloWorldImpl1.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl1.doPrint()"); return ; } }
public class HelloWorldImpl2 implements HelloWorld { public void printHelloWorld() { System.out.println("Enter HelloWorldImpl2.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl2.doPrint()"); return ; } }
橫切關注點,這裏是打印時間:
public class TimeHandler { public void printTime() { System.out.println("CurrentTime = " + System.currentTimeMillis()); } }
有這三個類就能夠實現一個簡單的Spring AOP了,看一下aop.xml的配置:
<?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:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /> <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /> <bean id="timeHandler" class="com.xrq.aop.TimeHandler" /> <aop:config> <aop:aspect id="time" ref="timeHandler"> <aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
<!--第一個*表示匹配任意的方法返回值,第二個*表示全部方法,..表示方法的任意參數個數-->
<aop:before method="printTime" pointcut-ref="addAllMethod" /> <aop:after method="printTime" pointcut-ref="addAllMethod" /> </aop:aspect> </aop:config> </beans>
使用一個main函數調用:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml"); HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1"); HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2"); hw1.printHelloWorld(); System.out.println(); hw1.doPrint(); System.out.println(); hw2.printHelloWorld(); System.out.println(); hw2.doPrint(); }
運行結果爲:
CurrentTime = 1446129611993 Enter HelloWorldImpl1.printHelloWorld() CurrentTime = 1446129611993 CurrentTime = 1446129611994 Enter HelloWorldImpl1.doPrint() CurrentTime = 1446129611994 CurrentTime = 1446129611994 Enter HelloWorldImpl2.printHelloWorld() CurrentTime = 1446129611994 CurrentTime = 1446129611994 Enter HelloWorldImpl2.doPrint() CurrentTime = 1446129611994
Spring注意事項
Spring的日誌輸出是依賴於commons-logging,可是spring的jar包中沒有給咱們提供,因此咱們須要本身進行下載。
Spring最主要的核心包是4個【 beans、context、core、expression】,一個簡單的spring須要着5個jar包便可,若是要擴展功能的話,咱們須要在源碼的libs中再從新引入所須要的jar包。
Spring在鏈接數據庫時,須要引入鏈接數據庫的jar包,這個也須要咱們另外下載
四.spring MVC
一、 用戶發送請求至前端控制器DispatcherServlet。
二、 DispatcherServlet收到請求調用HandlerMapping處理器映射器。
三、 處理器映射器找到具體的處理器(能夠根據xml配置、註解進行查找),生成處理器對象及處理器攔截器(若是有則生成)一併返回給DispatcherServlet。
四、 DispatcherServlet調用HandlerAdapter處理器適配器。
五、 HandlerAdapter通過適配調用具體的處理器(Controller,也叫後端控制器)。
六、 Controller執行完成返回ModelAndView。
七、 HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet。
八、 DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器。
九、 ViewReslover解析後返回具體View。
十、DispatcherServlet根據View進行渲染視圖(即將模型數據填充至視圖中)。
十一、 DispatcherServlet響應用戶。
4.2.組件:
一、前端控制器DispatcherServlet(不須要工程師開發),由框架提供
做用:接收請求,響應結果,至關於轉發器,中央處理器。有了dispatcherServlet減小了其它組件之間的耦合度。
用戶請求到達前端控制器,它就至關於mvc模式中的c,dispatcherServlet是整個流程控制的中心,由它調用其它組件處理用戶的請求,dispatcherServlet的存在下降了組件之間的耦合性。
二、處理器映射器HandlerMapping(不須要工程師開發),由框架提供
做用:根據請求的url查找Handler
HandlerMapping負責根據用戶請求找到Handler即處理器,springmvc提供了不一樣的映射器實現不一樣的映射方式,例如:配置文件方式,實現接口方式,註解方式等。
三、處理器適配器HandlerAdapter
做用:按照特定規則(HandlerAdapter要求的規則)去執行Handler
經過HandlerAdapter對處理器進行執行,這是適配器模式的應用,經過擴展適配器能夠對更多類型的處理器進行執行。
四、處理器Handler(須要工程師開發)
注意:編寫Handler時按照HandlerAdapter的要求去作,這樣適配器才能夠去正確執行Handler
Handler 是繼DispatcherServlet前端控制器的後端控制器,在DispatcherServlet的控制下Handler對具體的用戶請求進行處理。
因爲Handler涉及到具體的用戶業務請求,因此通常狀況須要工程師根據業務需求開發Handler。
五、視圖解析器View resolver(不須要工程師開發),由框架提供
做用:進行視圖解析,根據邏輯視圖名解析成真正的視圖(view)
View Resolver負責將處理結果生成View視圖,View Resolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果經過頁面展現給用戶。 springmvc框架提供了不少的View視圖類型,包括:jstlView、freemarkerView、pdfView等。
通常狀況下須要經過頁面標籤或頁面模版技術將模型數據經過頁面展現給用戶,須要由工程師根據業務需求開發具體的頁面。
六、視圖View(須要工程師開發jsp...)
View是一個接口,實現類支持不一樣的View類型(jsp、freemarker、pdf...)
4.3.springMVC-mvc.xml 配置文件片斷講解
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 自動掃描的包名 --> <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan> <!-- 默認的註解映射的支持 --> <mvc:annotation-driven /> <!-- 視圖解釋類 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/><!--可爲空,方便實現自已的依據擴展名來選擇視圖解釋類的邏輯 --> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean> <!-- 攔截器 --> <mvc:interceptors> <bean class="com.core.mvc.MyInteceptor" /> </mvc:interceptors> <!-- 對靜態資源文件的訪問 方案一 (二選一) --> <mvc:default-servlet-handler/> <!-- 對靜態資源文件的訪問 方案二 (二選一)--> <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/> <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/> </beans>
<context:component-scan/> 掃描指定的包中的類上的註解,經常使用的註解有:
@Controller 聲明Action組件
@Service 聲明Service組件 @Service("myMovieLister")
@Repository 聲明Dao組件
@Component 泛指組件, 當很差歸類時.
@RequestMapping("/menu") 請求映射
@Resource 用於注入,( j2ee提供的 ) 默認按名稱裝配,@Resource(name="beanName")
@Autowired 用於注入,(srping提供的) 默認按類型裝配
@Transactional( rollbackFor={Exception.class}) 事務管理
@ResponseBody
@Scope("prototype") 設定bean的做用域
@ModelAtrribute的運行流程
1.執行@ModelAtrribute註解修飾的方法:從數據庫中取出對象,並把對象放到了Map中,鍵爲user
2.springMVC從Map集合中取出User對象,並把表單的請求參數賦值給user對象相應的屬性
3.springMVC把上述對象傳入目標方法的參數
4.這個user對象是存在request中,若是jsp表單中有對應的字段,還會自動填充表單
注意:在@ModelAtrribute修飾的方法中,放入Map時的鍵要和目標方法的參數名一致
4.4.Converter與Formatter
Spring的Converter能夠將一種類型轉換成另外一種類型。
在使用時,必須編寫一個實現org.springframework.core.convert.converter.Converter接口的java類。這個接口的聲明以下
public interface Converter<S, T> { T convert(S var1); }
這裏的S表示源類型,T表示目標類型。
下面展現了一個將String類型轉換成Date類型的Converter
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.convert.converter.Converter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class StringToDateConverter implements Converter<String, Date>{ private static final Log logger = LogFactory.getLog(StringToDateConverter.class); private String datePattern; public StringToDateConverter(String datePattern) { this.datePattern = datePattern; } public Date convert(String s) { try { SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern); dateFormat.setLenient(false); return dateFormat.parse(s); } catch (ParseException e) { throw new IllegalArgumentException("invalid date format. Please use this pattern\"" + datePattern + "\""); } } }
爲了使用Spring MVC應用程序定製的Converter,須要在配置文件中添加一個conversionService bean。Bean的類名稱必須爲org.springframework.context.support.ConversionServiceFactoryBean。這個bean必須包含一個converters屬性,它列出要在應用程序中使用的全部定製Converter。下面bean聲明註冊了上面StringToDateConverter。
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="app06a.converter.StringToDateConverter"> <constructor-arg name="datePattern" value="yyyy-MM-dd"/> </bean> </set> </property> </bean>
以後,還須要給annotation-driven元素的conversion-service屬性賦上bean名稱,以下
2Formatter
Formatter和Converter同樣,也是將一種類型轉換成另外一種類型。可是,Formatter的源類型必須是一個String。
在使用時,必須編寫一個實現org.springframework.format.Formatter接口的java類。這個接口的聲明以下<mvc:annotation-driven conversion-service="conversionService"/>
public interface Formatter<T> extends Printer<T>, Parser<T> { } public interface Printer<T> { String print(T var1, Locale var2); } public interface Parser<T> { T parse(String var1, Locale var2) throws ParseException; }
這裏的T表示輸入字符串要轉換的目標類型。
parse方法利用指定的Locale將一個String解析成目標類型。print方法相反,它是返回目標對象的字符串表示法。
下面展現了一個將String類型轉換成Date類型的Formatter
import org.springframework.format.Formatter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class DateFormatter implements Formatter<Date>{ private String datePattern; private SimpleDateFormat dateFormat; public DateFormatter(String datePattern) { this.dateFormat = dateFormat; dateFormat = new SimpleDateFormat(datePattern); dateFormat.setLenient(false); } public Date parse(String s, Locale locale) throws ParseException { try { SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern); dateFormat.setLenient(false); return dateFormat.parse(s); } catch (ParseException e) { throw new IllegalArgumentException("invalid date format. Please use this pattern\"" + datePattern + "\""); } } public String print(Date date, Locale locale) { return dateFormat.format(date); } }
爲了使用Spring MVC應用程序定製的Formatter,須要在配置文件中添加一個conversionService bean。Bean的類名稱必須爲org.springframework.format.support.FormattingConversionServiceFactoryBean。這個bean能夠用一個formatters屬性註冊Formatter,用一個converters屬性註冊Converter。下面bean聲明註冊了上面DateFormatter。
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="app06a.formatter.DateFormatter"> <constructor-arg name="datePattern" value="yyyy-MM-dd"/> </bean> </set> </property> </bean>
以後,還須要給annotation-driven元素的conversion-service屬性賦上bean名稱,以下
<mvc:annotation-driven conversion-service="conversionService"/>
Converter是通常工具,能夠將一種類型轉換成另外一種類型。例如,將String轉換成Date,或者將Long轉換成Date。Converter既能夠用在web層,也能夠用在其它層中。
Formatter只能將String轉成成另外一種java類型。例如,將String轉換成Date,但它不能將Long轉換成Date。因此,Formatter適用於web層。爲此,在Spring MVC應用程序中,選擇Formatter比選擇Converter更合適。
4.5.Validator
4.6.Springmvc的優勢
1.它是基於組件技術的.所有的應用對象,不管控制器和視圖,仍是業務對象之類的都是 java組件.而且和Spring提供的其餘基礎結構緊密集成.
2.不依賴於Servlet API(目標雖是如此,可是在實現的時候確實是依賴於Servlet的)
3. 能夠任意使用各類視圖技術,而不只僅侷限於JSP
4 .支持各類請求資源的映射策略
5 .它應是易於擴展的