Spring
簡介
Spring 是一種用來簡化企業(yè)級應用開發(fā)的開源框架,包括Spring Framework, Spring Data, Spring Security柳沙,Spring Boot岩灭,SpringMVC等。Spring 家族最核心的概念當屬 AOP 和 IoC赂鲤,詳解見下節(jié)噪径。其中 Spring 優(yōu)點如下:
降低了組件之間的耦合性 ,實現(xiàn)了軟件各層之間的解耦
可以使用便捷的眾多服務数初,如事務管理找爱,消息服務等
容器提供了AOP技術,利用它很容易實現(xiàn)如權限攔截泡孩,運行期監(jiān)控等功能
Spring對于主流的應用框架提供了集成支持车摄,如Hibernate、JPA等
Spring屬于低侵入式設計,代碼的污染極低
Spring的高度開放性吮播,開發(fā)者可以自由選擇Spring的部分或全部
AOP和IOC
AOP(Aspect Oriented Programming变屁,面向切面編程)
AOP簡單說就是在目標方法執(zhí)行前后自定義一些操作,一般都是基于代理模式來實現(xiàn)的意狠,Spring支持兩種代理模式粟关,JDK原生代理和CGLib代理。AOP給程序帶來良好的擴展性和封裝性环戈,可以實現(xiàn)業(yè)務代碼與非業(yè)務代碼的隔離闷板。比如可以在不改變目標代碼的前提下實現(xiàn)目標方法的增強:埋點業(yè)務處理、方法執(zhí)行時間監(jiān)控谷市,打印日志蛔垢,權限控制等等。
JDK動態(tài)代理是利用反射機制生成一個實現(xiàn)代理接口的匿名類迫悠,在調用具體方法前調用InvokeHandler來處理鹏漆。只能對實現(xiàn)了接口的類生成代理。
CGLib動態(tài)代理是利用ASM開源包创泄,對代理對象類的Class文件加載進來艺玲,通過修改其字節(jié)碼生成子類來處理。
切面(Aspect):類是對物體特征的抽象鞠抑,切面就是對橫切關注點的抽象饭聚。
切點(Pointcut):對連接點進行攔截的定義。
連接點(Joinpoint):被攔截到的點搁拙,比如方法(Spring中一般是方法)秒梳、字段、構造器箕速。
通知(Advice):指攔截到連接點后要執(zhí)行的代碼酪碘,通知分為前置、后置盐茎、異常兴垦、最終、環(huán)繞五類字柠。
AOP:在運行時探越,動態(tài)地將代碼切入到類的指定方法、指定位置上的編程思想
IoC(Inversion of Control窑业,控制反轉)
IOC (Inversion of Control钦幔,控制反轉):對象之間的依賴關系由容器來創(chuàng)建。本來對象之間的關系是由開發(fā)者自己創(chuàng)建和維護的数冬,在使用Spring框架后节槐,對象之間的關系由容器來創(chuàng)建和維護搀庶,將開發(fā)者做的事讓容器做拐纱,這就是控制反轉铜异。BeanFactory接口是Spring Ioc容器的核心接口。
DI (Dependecy Injection秸架,依賴注入):我們在使用Spring容器的時候揍庄,容器通過調用set方法或者是構造器來建立對象之間的依賴關系。注入方式有設值注入东抹、構造注入蚂子、注解注入、接口注入(基本不用)缭黔,設值注入直觀食茎,自然;構造注入可以在構造器中決定依賴關系的順序馏谨。
控制反轉是目標别渔,依賴注入是我們實現(xiàn)控制反轉的一種手段。
SpringMVC和Struts
SpringMVC執(zhí)行流程如下:
客戶端向Spring容器發(fā)起一個HTTP請求惧互。
發(fā)起的請求被前端控制器(DispatcherServlet)攔截哎媚。
查詢處理器映射(HandlerMapping)得到執(zhí)行鏈,并請求相應的處理器適配器(HandlerAdapter)喊儡。
執(zhí)行處理器(Handler)并處理請求拨与,以ModelAndView(屬性值和返回頁面)的形式返回。此處Handler即平時編寫的Controller艾猜。
前端控制器查詢視圖解析器(ViewResolver)买喧,并返回View。
成功渲染視圖則返回給客戶端匆赃,否則拋異常淤毛。
比較點SpringMVCStruts核心控制器DispatcherServletFilterDispatcher配置文件量少(AOP)量大(Interceptor機制)RESTful API易實現(xiàn)(方法級別)實現(xiàn)費勁(類級別)處理Ajax請求@ResponseBody返回響應文本攔截器集成Ajax性能稍快稍慢
DispatcherServlet初始化流程如下:
加載配置文件
掃描所有的相關類
初始化所有相關類的Class實例,并將其保存到IoC容器
自動化的依賴注入(Autowired)
初始化HandlerMapping
Spring事務
數(shù)據(jù)庫事務是指作為單個邏輯工作單元執(zhí)行的一系列操作炸庞,要么完全地執(zhí)行钱床,要么完全地不執(zhí)行。事務滿足原子性(Atomicity)埠居、一致性(Consistency)查牌、隔離性(Isolation)、持久性(Durability) 四大特性滥壕。
事務隔離級別
數(shù)據(jù)讀的三類問題:
問題解釋臟讀事務 A 讀取了事務 B 未提交的數(shù)據(jù)(發(fā)現(xiàn)讀到的數(shù)據(jù)是臟數(shù)據(jù))不可重復讀事務 A 讀取了事務 B 已提交的更改數(shù)據(jù)(發(fā)現(xiàn)與前一次讀的不一致)幻讀事務 A 讀取了事務 B 已提交的新增數(shù)據(jù)(發(fā)現(xiàn)之前沒有這條數(shù)據(jù)的)
事務的四種隔離級別見下表纸颜,MySQL默認為REPEATABLE_READ:
隔離級別(簡寫)含義隱患READ_UNCOMMITTED允許讀未提交臟讀、不可重復讀绎橘、幻讀READ_COMMITTED允許讀已提交不可重復讀胁孙、幻讀REPEATABLE_READ允許重復讀幻讀SERIALIZABLE序列化讀–
事務管理
Spring事務管理器的接口是PlatformTransactionManager唠倦,通過這個接口,Spring為各個平臺如JDBC(DataSourceTransactionManager)涮较、Hibernate(HibernateTransactionManager冕茅、JpaTransactionManager)等都提供了對應的事務管理器。
事務的傳播特性
當事務方法被另一個事務方法調用時仁烹,必須指定事務應該如何傳播蚊锹,根據(jù)如下代碼中方法 A 有無事務,Spring定義了7種傳播行為(默認為REQUIRED):
@Transactionalvoid A(){ }@Transactionalvoid B(){A(); }
傳播行為(簡寫)含義REQUIRED如果沒有闺属,就開啟一個事務慌盯;如果有,就加入當前事務(方法A加入到方法B)REQUIRES_NEW如果沒有掂器,就開啟一個事務亚皂;如果有,就將當前事務掛起NESTED如果沒有国瓮,就開啟一個事務灭必;如果有,就在當前事務中嵌套其他事務(主事務提交或回滾巍膘,子事務也會提交或回滾)SUPPORTS如果沒有厂财,就以非事務方式執(zhí)行;如果有峡懈,就使用當前事務NOT_SUPPORTED如果沒有璃饱,就以非事務方式執(zhí)行;如果有肪康,就將當前事務掛起NEVER如果沒有荚恶,就以非事務方式執(zhí)行;如果有磷支,就拋出異常MANDATORY如果沒有谒撼,就拋出異常;如果有雾狈,就使用當前事務
Spring Boot
Spring Boot來自于 Spring 大家族廓潜,是一套全新的框架,它默認幫我們進行了很多配置善榛,集成了大量常用的第三方庫(例如 Jackson辩蛋、JDBC、MongoDB移盆、Redis悼院、Mail 等),這些第三方庫幾乎都可以開箱即用咒循。Spring Boot可以幫助我們快速搭建一個項目据途,從而讓開發(fā)者能夠更加專注于業(yè)務邏輯绞愚。
Spring擴展
實現(xiàn)BeanPostProcess接口在Bean生成前后進行操作。
實現(xiàn)BeanFactoryPostProcessor接口配置Bean元屬性颖医。
實現(xiàn)FactoryBean接口定制個性化的Bean位衩。
MyBatis
MyBatis是一款優(yōu)秀的持久層框架,它幾乎避免了所有的JDBC代碼和手動設置參數(shù)以及獲取結果集便脊,它可以使用XML或注解來將接口和POJO映射成數(shù)據(jù)庫中的記錄蚂四。
MyBatis與Spring集成的時候Spring提供了全局唯一的SqlSessionTemplate光戈,SqlSessionTemplate 實現(xiàn)了SqlSession接口哪痰,那么如何保證多個線程調用同一個dao時拿到的SqlSession不會錯亂呢?這個時候就用到了ThreadLocal久妆,SqlSessionUtils.getSqlSession()會首先查看當前線程資源map有無SqlSession晌杰,有則返回無則新建然后返回,這樣就能保證一條業(yè)務始終用的是同一個數(shù)據(jù)庫連接筷弦,也就能正確處理數(shù)據(jù)庫事務肋演。
MyBatis和Hibernate
比較點MyBatisHibernate特點半自動(手寫SQL)全自動(根據(jù)映射生成SQL)SQL直接優(yōu)化方便復雜數(shù)據(jù)庫移植性弱強緩存機制欠缺更優(yōu)日志系統(tǒng)欠缺完整
Statement和PreparedStatement的區(qū)別
/PreparedStatement extends Statement///Statement用法sql1 ="select * from tbl_user where username='"+ u +"' and password='"+ p +"'";statement = conn.createStatement(); result1 = statement.executeQuery(sql1); //PrepareStatement用法sql2 ="select * from tbl_user where username=? and password=?"; prepareStatement = conn.prepareStatement(sql2); pstmt.setString(1, u); pstmt.setString(2, p); result2 = prepareStatement.executeQuery();
比較點StatementPreparedStatement用途執(zhí)行靜態(tài)SQL語句并返回結果執(zhí)行已預編譯SQL語句并返回結果可讀性低(字符串拼接)高(Set方法設值)效率低(字符串拼接)高(占位符)安全性低(SQL注入)高
消息隊列
消息隊列中間件是分布式系統(tǒng)中重要的組件,主要主要解決應用耦合烂琴、異步消息爹殊、流量削鋒等問題,具有異步性奸绷、可靠性(存儲到本地硬盤)梗夸、松耦合、分布式的特性号醉。
主要特點是異步處理
主要目的是減少請求響應時間反症、解耦
主要使用場景是將比較耗時且不需同步返回結果的操作當做消息存入隊列
流量削峰的一種解決方案
MQ推送模式改為定時或者批量拉取模式
消息接收方實現(xiàn)批量處理等方式
RabbitMQ
RabbitMQ 是一個由 ErLang 開發(fā)的AMQP的開源實現(xiàn)。
交換機(Exchange)的功能主要是接收消息并且轉發(fā)到綁定的隊列畔派,交換機不存儲消息铅碍,交換機本質是一張路由查詢表。
Direct:綁定時設定一個路由鍵线椰,消息的路由鍵匹配才會被投送到隊列中胞谈。
Topic:根據(jù)模糊匹配轉發(fā)消息(最靈活)。
Headers:設置頭部參數(shù)類型的交換機憨愉。
Fanout:轉發(fā)消息到所有綁定隊列烦绳,消息廣播的模式。
路由鍵(routing_key)在消息中莱衩,而綁定鍵(binding_key)作用于交換機和隊列之間爵嗅。當消息中的路由鍵和綁定鍵對應上的時候,交換機就知道將該消息存入哪個隊列笨蚁。
分布式
分布式:一個業(yè)務分拆多個子業(yè)務睹晒,部署在不同的服務器上(廚師和配菜師的關系)
集群:同一個業(yè)務趟庄,部署在多個服務器上(兩個廚師的關系)
微服務
微服務架構風格是一種使用一套小服務來開發(fā)單個應用的方式,每個服務運行在自己的進程中伪很,并使用輕量級機制通信(通常是HTTP API)戚啥,這些服務能夠通過自動化部署機制來獨立部署、可以使用不同的編程語言實現(xiàn)锉试、可以使用不同的數(shù)據(jù)存儲技術猫十,并保持最低限度的集中式管理。
時下熱門的微服務開發(fā)框架有:Spring Cloud呆盖、Dubbo
RESTful
URL定位資源拖云,HTTP動詞描述操作
GET:讀取資源
POST:創(chuàng)建資源
PUT:更新資源
DELETE:刪除資源
使用PUT方式更新時,必須發(fā)送資源所有的屬性
Nginx
反向代理
正向代理:隱藏真實的請求客戶端应又,服務端不知道真實的客戶端是誰宙项,正向代理服務器會代替客戶端向服務器發(fā)送請求。正向代理代理的對象是客戶端株扛。
反向代理:隱藏真實的響應服務端尤筐,客戶端不知道真實的服務端是誰,反向代理服務器會把請求轉發(fā)到真實的服務器洞就。反向代理代理的對象是服務端盆繁。
10086總機就是一種反向代理,客戶不知道真正提供服務人的是誰旬蟋。
負載均衡
四層負載均衡:工作在OSI模型的傳輸層油昂,它在接收到客戶端的流量以后通過修改數(shù)據(jù)包的地址信息將流量轉發(fā)到應用服務器,因此四層負載均衡的主要工作就是轉發(fā)咖为。
七層負載均衡:工作在OSI模型的應用層秕狰,七層負載均衡在接到客戶端的流量以后,還需要一個完整的TCP/IP協(xié)議棧與客戶端建立一條完整的連接躁染,并將應用層的請求流量解析出來鸣哀,再按照調度算法選擇一個應用服務器,并與應用服務器建立另外一條連接將請求發(fā)送過去吞彤,因此七層負載均衡的主要工作就是代理我衬。
設計模式
設計模式的六大原則
單一職責原則:一個類只負責一個功能領域中的相應職責。
開閉原則:一個軟件實體應當對擴展開放饰恕,對修改關閉挠羔。
里氏替換原則:所有引用父類的地方必須能透明地使用其子類的對象。
依賴倒置原則:抽象不應該依賴于細節(jié)埋嵌,細節(jié)應當依賴于抽象破加。(要針對接口編程,而不是針對實現(xiàn)編程)雹嗦。
接口隔離原則:使用多個專門的接口范舀,而不使用單一的總接口合是。
迪米特法則:一個軟件實體應當盡可能少地與其他實體發(fā)生相互作用。
單例锭环、工廠聪全、觀察者、適配器辅辩、責任鏈
單例模式:一個類負責創(chuàng)建自己的對象难礼,同時確保只有單個對象被創(chuàng)建,并提供一種訪問其唯一對象的方式玫锋。
工廠模式:在創(chuàng)建對象時不暴露創(chuàng)建邏輯蛾茉,并通過使用一個共同的接口來指向新創(chuàng)建的對象。
觀察者模式:定義對象間的一種一對多的依賴關系景醇,當一個對象的狀態(tài)發(fā)生改變時臀稚,所有依賴于它的對象都得到通知并被自動更新。
適配器模式:負責加入獨立的或不兼容的接口功能的類三痰,使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
責任鏈模式:為請求創(chuàng)建了一個接收者對象的鏈窜管,沿著這條鏈傳遞請求散劫,直到有對象處理它為止,對請求的發(fā)送者和接收者進行解耦幕帆。
寫出生產(chǎn)者消費者模式
生產(chǎn)者生產(chǎn)數(shù)據(jù)到緩沖區(qū)中获搏,消費者從緩沖區(qū)中取數(shù)據(jù)。如果緩沖區(qū)已經(jīng)滿了失乾,則生產(chǎn)者線程阻塞常熙;如果緩沖區(qū)為空,那么消費者線程阻塞碱茁。
publicclassProducerAndConsumer{ staticBlockingQueueresourceQueue =newLinkedBlockingQueue(10); public static void main(String[] args) {Producerp =newProducer();//生產(chǎn)者Consumerc1 =newConsumer();//消費者1Consumerc2 =newConsumer();//消費者2Consumerc3 =newConsumer();//消費者3p.start(); c1.start(); c2.start(); c3.start(); }}/**
- 資源
/classResource{ int id; publicResource(int id) {this.id = id; }}/*
- 生產(chǎn)者
/classProducerextendsThread{ int p =1;@Overridepublic void run() {while(true) {try{Resourceresource =newResource(p++);System.out.println("生產(chǎn)資源"+ resource.id);ProducerAndConsumer.resourceQueue.put(resource); }catch(InterruptedExceptione) { e.printStackTrace(); } } }}/*
- 消費者
*/classConsumerextendsThread{@Overridepublic void run() {while(true) {try{System.out.println("消費資源"+ ((Resource)ProducerAndConsumer.resourceQueue.take()).id); }catch(InterruptedExceptione) { e.printStackTrace(); } } }}
高內聚裸卫、低耦合
耦合性:也稱塊間聯(lián)系。指軟件各模塊之間相互聯(lián)系緊密程度的一種度量纽竣。模塊之間聯(lián)系越緊密墓贿,則其耦合性就越強。模塊間耦合高低取決于模塊間接口的復雜性蜓氨、調用的方式及傳遞的信息聋袋。
內聚性:也稱塊內聯(lián)系。指軟件模塊內部各元素彼此結合緊密程度的一種度量穴吹。模塊內各元素(語名之間幽勒、程序段之間)聯(lián)系越緊密,則其內聚性就越高港令。
高內聚啥容、低耦合的系統(tǒng)具有更好的重用性棘钞,維護性,擴展性干毅,可以更高效的完成系統(tǒng)的維護開發(fā)宜猜,持續(xù)的支持業(yè)務的發(fā)展,而不會成為業(yè)務發(fā)展的障礙