Spring與SpringMVC
Spring是一個(gè)一站式的框架爬橡,提供了表現(xiàn)層(SpringMVC/Struts)到業(yè)務(wù)層(Spring)再到數(shù)據(jù)層(Hibernate/Mybatis)都提供了多種配置解決方案;Spring的兩大核心IOC(控制反轉(zhuǎn))和AOP(面向切面編程)更是給我們的程序解耦和代碼的簡(jiǎn)介提供了支持棒动。
即Spring在JavaEE的三層架構(gòu)[表現(xiàn)層(Web層)糙申、業(yè)務(wù)邏輯層(Service層)、數(shù)據(jù)訪問層(DAO層)]中船惨,每一層均提供了不同的解決技術(shù)柜裸。如下:
? 表現(xiàn)層(Web層):Spring MVC
? 業(yè)務(wù)邏輯層(Service層):Spring的IoC
? 數(shù)據(jù)訪問層(DAO層):Spring的jdbcTemplate
Spring是IOC和AOP的容器框架,SpringMVC是基于Spring功能之上添加的Web框架掷漱,想用SpringMVC必須先依賴Spring粘室。
Spring MVC通過Dispatcher Servlet, ModelAndView 和 View Resolver,開發(fā)web應(yīng)用變得很容易卜范。主要針對(duì)的是網(wǎng)站應(yīng)用程序或者服務(wù)開發(fā)——URL路由衔统、Session、模板引擎海雪、靜態(tài)Web資源等等锦爵。
-
SpringMVC的執(zhí)行流程
1、 用戶發(fā)送請(qǐng)求至前端控制器DispatcherServlet奥裸;
2险掀、DispatcherServlet收到請(qǐng)求調(diào)用HandlerMapping處理器映射器;
3湾宙、處理器映射器根據(jù)請(qǐng)求url找到具體的處理器樟氢,生成處理器對(duì)象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet冈绊;
4、DispatcherServlet通過HandlerAdapter處理器適配器調(diào)用處理器埠啃,執(zhí)行處理器(Controller死宣,也叫后端控制器);
5碴开、Controller執(zhí)行完成返回ModelAndView毅该,并返回給HandlerAdapter,HandlerAdapter將結(jié)果返回給DispatcherServlet潦牛;
6眶掌、DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器,ViewReslover解析后返回具體View給DispatcherServlet巴碗;
7朴爬、DispatcherServlet對(duì)View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)后返回給給客戶
-
Spring的優(yōu)點(diǎn)
1、降低了組件之間的耦合性 良价,實(shí)現(xiàn)了軟件各層之間的解耦
2寝殴、容器提供單例模式支持
????在Spring中,bean可以被定義為兩種模式:prototype(多例)和singleton(單例), 默認(rèn)是單例模式明垢。
????2.1蚣常、singleton(單例):只有一個(gè)共享的實(shí)例存在,所有對(duì)這個(gè)bean的請(qǐng)求都會(huì)返回這個(gè)唯一的實(shí)例痊银。
????2.2抵蚊、prototype(多例):對(duì)這個(gè)bean的每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的bean實(shí)例,類似于new溯革。
3贞绳、容器提供了AOP技術(shù),利用它很容易實(shí)現(xiàn)如權(quán)限攔截致稀,運(yùn)行期監(jiān)控等功能
4冈闭、Spring對(duì)于主流的應(yīng)用框架提供了集成支持,如hibernate抖单,JPA萎攒,Struts等
5、spring的DI機(jī)制降低了業(yè)務(wù)對(duì)象替換的復(fù)雜性
-
什么是DI機(jī)制矛绘?
依賴注入(Dependecy Injection)和控制反轉(zhuǎn)(Inversion of Control)是同一個(gè)概念耍休,具體的講:當(dāng)某個(gè)角色需要另外一個(gè)角色協(xié)助的時(shí)候,在傳統(tǒng)的程序設(shè)計(jì)過程中货矮,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實(shí)例羊精。
但在Spring中創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來完成,因此稱為控制反轉(zhuǎn)囚玫。創(chuàng)建被調(diào)用者的工作由Spring來完成喧锦,然后注入調(diào)用者因此也稱為依賴注入读规。
Spring以動(dòng)態(tài)靈活的方式來管理對(duì)象 , 注入的兩種方式燃少,設(shè)置注入和構(gòu)造注入掖桦。
設(shè)置注入的優(yōu)點(diǎn):直觀,自然
構(gòu)造注入的優(yōu)點(diǎn):可以在構(gòu)造器中決定依賴關(guān)系的順序供汛。
-
Spring的IOC
Spring IOC(控制反轉(zhuǎn),也可以稱為依賴倒置)涌穆,將傳統(tǒng)的對(duì)象創(chuàng)建流程轉(zhuǎn)變?yōu)榻挥蒘pring框架進(jìn)行創(chuàng)建和管理怔昨。Spring IOC操作分為:IOC配置文件方式和IOC的注解方式。
-
Spring的AOP
面向切面編程(AOP)是對(duì)面向?qū)ο缶幊蹋∣OP)的補(bǔ)充宿稀,面向切面編程在Spring中主要表現(xiàn)為兩個(gè)方面:
1趁舀、面向切面編程提供聲明式事務(wù)管理
2、Spring支持用戶自定義的切面
AOP采取橫向抽取機(jī)制祝沸,取代了傳統(tǒng)縱向繼承體系重復(fù)性代碼矮烹,例如:事務(wù)管理、性能監(jiān)視罩锐、安全檢查奉狈、緩存 、日志等涩惑。
AOP實(shí)現(xiàn)原理:
1仁期、AOP底層將采用代理機(jī)制進(jìn)行實(shí)現(xiàn)。
2竭恬、接口 + 實(shí)現(xiàn)類 :Spring采用 JDK的動(dòng)態(tài)代理Proxy跛蛋。
3、實(shí)現(xiàn)類:Spring采用 Cglib字節(jié)碼增強(qiáng)痊硕。
JDK動(dòng)態(tài)代理
public static UserService createService(){
//1 目標(biāo)類
final UserService userService = new UserServiceImpl();
//2切面類
final MyAspect aspect = new MyAspect();
/* 3 代理類:將目標(biāo)類(切入點(diǎn))和 切面類(通知) 結(jié)合 --> 切面
* Proxy.newProxyInstance
* 參數(shù)1:loader 赊级,類加載器,動(dòng)態(tài)代理類 運(yùn)行時(shí)創(chuàng)建岔绸,任何類都需要類加載器將其加載到內(nèi)存理逊。
* 一般情況:當(dāng)前類.class.getClassLoader();
* 目標(biāo)類實(shí)例.getClass().get...
* 參數(shù)2:Class[] interfaces 代理類需要實(shí)現(xiàn)的所有接口
* 方式1:目標(biāo)類實(shí)例.getClass().getInterfaces() ;注意:只能獲得自己接口,不能獲得父元素接口
* 方式2:new Class[]{UserService.class}
* 例如:jdbc 驅(qū)動(dòng) --> DriverManager 獲得接口 Connection
* 參數(shù)3:InvocationHandler 處理類亭螟,接口挡鞍,必須進(jìn)行實(shí)現(xiàn)類,一般采用匿名內(nèi)部
* 提供 invoke 方法预烙,代理類的每一個(gè)方法執(zhí)行時(shí)墨微,都將調(diào)用一次invoke
* 參數(shù)31:Object proxy :代理對(duì)象
* 參數(shù)32:Method method : 代理對(duì)象當(dāng)前執(zhí)行的方法的描述對(duì)象(反射)
* 執(zhí)行方法名:method.getName()
* 執(zhí)行方法:method.invoke(對(duì)象,實(shí)際參數(shù))
* 參數(shù)33:Object[] args :方法實(shí)際參數(shù)
*
*/
UserService proxyService = (UserService)Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前執(zhí)行
aspect .before();
//執(zhí)行目標(biāo)類的方法
Object obj = method.invoke(userService, args);
//后執(zhí)行
aspect .after();
return obj;
}
});
return proxyService;
}
Spring的CGLIB字節(jié)碼增強(qiáng)
public static UserServiceImpl createService(){
//1 目標(biāo)類
final UserServiceImpl userService = new UserServiceImpl();
//2切面類
final MyAspect myAspect = new MyAspect();
// 3.代理類 扁掸,采用cglib翘县,底層創(chuàng)建目標(biāo)類的子類
//3.1 核心類
Enhancer enhancer = new Enhancer();
//3.2 確定父類
enhancer.setSuperclass(userService.getClass());
/* 3.3 設(shè)置回調(diào)函數(shù) , MethodInterceptor接口 等效 jdk InvocationHandler接口
* intercept() 等效 jdk invoke()
* 參數(shù)1最域、參數(shù)2、參數(shù)3:以invoke一樣
* 參數(shù)4:methodProxy 方法的代理
*/
enhancer.setCallback(new MethodInterceptor(){
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//前執(zhí)行
myAspect.before();
//執(zhí)行目標(biāo)類的方法
Object obj = method.invoke(userService, args);
// * 執(zhí)行代理類的父類 锈麸,執(zhí)行目標(biāo)類 (目標(biāo)類和代理類 父子關(guān)系)
methodProxy.invokeSuper(proxy, args);
//后執(zhí)行
myAspect.after();
return obj;
}
});
//3.4 創(chuàng)建代理
UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
return proxService;
}
注解方式
/*
* 聲明一個(gè)切面
* 自動(dòng)注解AOP
*/
@Aspect
@Component(value="aopDemoOrder")
public class AopDemoOrder {
// 配置切點(diǎn) 及要傳的參數(shù)
@Pointcut("execution(* com.spring.aop.OrderService.GetDemoOrder(..)) && args(id)")
public void pointCut(int id)
{
}
// 配置連接點(diǎn) 方法開始執(zhí)行前通知
@Before("pointCut(id)")
public void beforeLog(int id) {
System.out.println("開始執(zhí)行前置通知 日志記錄:"+id);
}
// 方法執(zhí)行完后通知
@After("pointCut(id)")
public void afterLog(int id) {
System.out.println("方法執(zhí)行完后置通知 日志記錄:"+id);
}
// 執(zhí)行成功后通知
@AfterReturning("pointCut(id)")
public void afterReturningLog(int id) {
System.out.println("方法成功執(zhí)行后通知 日志記錄:"+id);
}
// 拋出異常后通知
@AfterThrowing("pointCut(id)")
public void afterThrowingLog(int id) {
System.out.println("方法拋出異常后通知 日志記錄"+id);
}
// 環(huán)繞通知
@Around("pointCut(id)")
public Object aroundLog(ProceedingJoinPoint joinpoint, int id) {
Object result = null;
try {
System.out.println("環(huán)繞通知開始 日志記錄"+id);
long start = System.currentTimeMillis();
//有返回參數(shù) 則需返回值
result = joinpoint.proceed();
} catch (Throwable t) {
System.out.println("出現(xiàn)錯(cuò)誤");
}
return result;
}
}
-
BeanFactory與FactoryBean
1镀脂、BeanFactory是個(gè)Factory,也就是IOC容器或?qū)ο蠊S忘伞。在Spring中薄翅,所有的Bean都是由BeanFactory(也就是IOC容器)來進(jìn)行管理的。
2氓奈、FactoryBean是Spring通過反射機(jī)制利用<bean>的class屬性指定實(shí)現(xiàn)類實(shí)例化Bean翘魄,在某些情況下,實(shí)例化Bean過程比較復(fù)雜舀奶,如果按照傳統(tǒng)的方式暑竟,則需要在<bean>中提供大量的配置信息。Spring為此提供了一個(gè)org.springframework.bean.factory.FactoryBean的工廠類接口育勺,用戶可以通過實(shí)現(xiàn)該接口定制實(shí)例化Bean的邏輯但荤。
SpringBoot與SpringCloud
Spring Boot,看名字就知道是Spring的一套快速配置腳手架涧至,可以基于Spring Boot快速開發(fā)單個(gè)微服務(wù)腹躁。
Spring Cloud基于Spring Boot,為微服務(wù)體系開發(fā)中的架構(gòu)問題南蓬,提供了一整套的解決方案——服務(wù)注冊(cè)與發(fā)現(xiàn)潜慎,服務(wù)消費(fèi),服務(wù)保護(hù)與熔斷蓖康,網(wǎng)關(guān)铐炫,分布式調(diào)用追蹤,分布式配置管理等蒜焊。
Spring Boot可以離開Spring Cloud獨(dú)立使用開發(fā)項(xiàng)目倒信,但是Spring Cloud離不開Spring Boot,屬于依賴的關(guān)系泳梆。
總結(jié)
1鳖悠、 Spring 框架就像一個(gè)家族,有眾多衍生產(chǎn)品例如 boot优妙、security乘综、jpa等等。但他們的基礎(chǔ)都是Spring的IOC套硼、AOP等卡辰, IOC提供了依賴注入的容器, AOP解決了面向橫切面編程,然后在此兩者的基礎(chǔ)上實(shí)現(xiàn)了其他延伸產(chǎn)品的高級(jí)功能九妈;
2反砌、 SpringMVC是基于Servlet 的一個(gè)MVC框架主要解決Web開發(fā)的問題,因?yàn)镾pring的配置非常復(fù)雜萌朱,各種XML宴树、JavaConfig、servlet處理起來比較繁瑣晶疼;
3酒贬、為了簡(jiǎn)化開發(fā)者的使用,推出了Spring Boot框架默認(rèn)優(yōu)于配置翠霍,簡(jiǎn)化了SpringMVC的配置流程同衣;但區(qū)別于SpringBoot專注于微服務(wù)方面的接口開發(fā),和前端解耦壶运,雖然SpringBoot也可以做成SpringMVC前后臺(tái)一起開發(fā),但是這就有點(diǎn)不符合SpringBoot框架的初衷了浪秘;
4.蒋情、SpringCloud關(guān)注的是全局微服務(wù)的整合和管理,相當(dāng)于管理多個(gè)SpringBoot框架的單體微服務(wù)耸携;為微服務(wù)體系開發(fā)中的架構(gòu)問題棵癣,提供了一整套的解決方案。