什么是Spring
Spring 是個(gè)java企業(yè)級(jí)應(yīng)用的開源開發(fā)框架对省。Spring主要用來開發(fā)Java應(yīng)用,但是有些擴(kuò)展是針對(duì)構(gòu)建J2EE平臺(tái)的web應(yīng)用盾似。Spring 框架目標(biāo)是簡(jiǎn)化Java企業(yè)級(jí)應(yīng)用開發(fā)隘竭,并通過POJO為基礎(chǔ)的編程模型促進(jìn)良好的編程習(xí)慣。
Spring有什么好的
輕量:Spring 是輕量的定踱,基本的版本大約2MB
控制反轉(zhuǎn):Spring通過控制反轉(zhuǎn)實(shí)現(xiàn)了松散耦合,對(duì)象們給出它們的依賴恃鞋,而不是創(chuàng)建或查找依賴的對(duì)象們
面向切面的編程(AOP):Spring支持面向切面的編程崖媚,并且把應(yīng)用業(yè)務(wù)邏輯和系統(tǒng)服務(wù)分開
容器:Spring 包含并管理應(yīng)用中對(duì)象的生命周期和配置
MVC框架:Spring的WEB框架是個(gè)精心設(shè)計(jì)的框架,是Web框架的一個(gè)很好的替代品
事務(wù)管理:Spring 提供一個(gè)持續(xù)的事務(wù)管理接口恤浪,可以擴(kuò)展到上至本地事務(wù)下至全局事務(wù)(JTA)
異常處理:Spring 提供方便的API把具體技術(shù)相關(guān)的異常(比如由JDBC畅哑,Hibernate or JDO拋出的)轉(zhuǎn)化為一致的unchecked 異常
spring IOC和DI的理解
IoC Inverse of Control 反轉(zhuǎn)控制的概念,就是將原本在程序中手動(dòng)創(chuàng)建UserService對(duì)象的控制權(quán)资锰,交由Spring框架管理敢课,簡(jiǎn)單說,就是創(chuàng)建UserService對(duì)象控制權(quán)被反轉(zhuǎn)到了Spring框架
DI:Dependency Injection 依賴注入绷杜,在Spring框架負(fù)責(zé)創(chuàng)建Bean對(duì)象時(shí)直秆,動(dòng)態(tài)的將依賴對(duì)象注入到Bean組件
IoC 控制反轉(zhuǎn),指將對(duì)象的創(chuàng)建權(quán)鞭盟,反轉(zhuǎn)到Spring容器 圾结, DI 依賴注入,指Spring創(chuàng)建對(duì)象的過程中齿诉,將對(duì)象依賴屬性通過配置進(jìn)行注入
BeanFactory 接口和 ApplicationContext 接口
①ApplicationContext 接口繼承BeanFactory接口筝野,Spring核心工廠是BeanFactory ,BeanFactory采取延遲加載晌姚,第一次getBean時(shí)才會(huì)初始化Bean, ApplicationContext是會(huì)在加載配置文件時(shí)初始化Bean。
②ApplicationContext是對(duì)BeanFactory擴(kuò)展歇竟,它可以進(jìn)行國(guó)際化處理挥唠、事件傳遞和bean自動(dòng)裝配以及各種不同應(yīng)用層的Context實(shí)現(xiàn)
開發(fā)中基本都在使用ApplicationContext, web項(xiàng)目使用WebApplicationContext ,很少用到BeanFactory
ApplicationContext通常的實(shí)現(xiàn)是什么焕议?
FileSystemXmlApplicationContext :此容器從一個(gè)XML文件中加載beans的定義宝磨,XML Bean 配置文件的全路徑名必須提供給它的構(gòu)造函數(shù)。
ClassPathXmlApplicationContext:此容器也從一個(gè)XML文件中加載beans的定義盅安,這里唤锉,你需要正確設(shè)置classpath因?yàn)檫@個(gè)容器將在classpath里找bean配置。
WebXmlApplicationContext:此容器加載一個(gè)XML文件别瞭,此文件定義了一個(gè)WEB應(yīng)用的所有bean窿祥。
Spring的WEB模塊是構(gòu)建在application context 模塊基礎(chǔ)之上,提供一個(gè)適合web應(yīng)用的上下文蝙寨。這個(gè)模塊也包括支持多種面向web的任務(wù)晒衩,如透明地處理多個(gè)文件上傳請(qǐng)求和程序級(jí)請(qǐng)求參數(shù)的綁定到你的業(yè)務(wù)對(duì)象。
Spring beans 是那些形成Spring應(yīng)用的主干的java對(duì)象籽慢。它們被Spring IOC容器初始化浸遗,裝配,和管理箱亿。這些beans通過容器中配置的元數(shù)據(jù)創(chuàng)建。比如弃秆,以XML文件中<bean/> 的形式定義届惋。
Spring 框架定義的beans都是單件beans。在bean tag中有個(gè)屬性”singleton”菠赚,如果它被賦為TRUE脑豹,bean 就是單件,否則就是一個(gè)
prototype bean衡查。默認(rèn)是TRUE瘩欺,所以所有在Spring框架中的beans 缺省都是單件。
spring的生命周期
在配置 <bean> 元素拌牲,通過 init-method 指定Bean的初始化方法俱饿,通過 destroy-method 指定Bean銷毀方法
- Spring容器 從XML 文件中讀取bean的定義,并實(shí)例化bean塌忽。
- Spring根據(jù)bean的定義填充所有的屬性拍埠。
- 如果bean實(shí)現(xiàn)了BeanNameAware 接口,Spring 傳遞bean 的ID 到 setBeanName方法土居。
- 如果Bean 實(shí)現(xiàn)了 BeanFactoryAware 接口枣购, Spring傳遞beanfactory 給setBeanFactory 方法嬉探。
- 如果有任何與bean相關(guān)聯(lián)的BeanPostProcessors,Spring會(huì)在postProcesserBeforeInitialization()方法內(nèi)調(diào)用它們棉圈。
- 如果bean實(shí)現(xiàn)IntializingBean了涩堤,調(diào)用它的afterPropertySet方法,如果bean聲明了初始化方法分瘾,調(diào)用此初始化方法胎围。
- 如果有BeanPostProcessors 和bean 關(guān)聯(lián),這些bean的postProcessAfterInitialization() 方法將被調(diào)用芹敌。
- 如果bean實(shí)現(xiàn)了 DisposableBean痊远,它將調(diào)用destroy()方法。
Spring MVC
Spring 配備構(gòu)建Web 應(yīng)用的全功能MVC框架氏捞。Spring可以很便捷地和其他MVC框架集成碧聪,如Struts,Spring 的MVC框架用控制反轉(zhuǎn)把業(yè)務(wù)對(duì)象和控制邏輯清晰地隔離液茎。它也允許以聲明的方式把請(qǐng)求參數(shù)和業(yè)務(wù)對(duì)象綁定逞姿。
DispatcherServlet
Spring的MVC框架是圍繞DispatcherServlet來設(shè)計(jì)的,它用來處理所有的HTTP請(qǐng)求和響應(yīng)捆等。
WebApplicationContext
WebApplicationContext 繼承了ApplicationContext 并增加了一些WEB應(yīng)用必備的特有功能滞造,它不同于一般的ApplicationContext ,因?yàn)樗芴幚碇黝}栋烤,并找到被關(guān)聯(lián)的servlet谒养。
- 用戶向服務(wù)器發(fā)送請(qǐng)求,請(qǐng)求被Spring 前端控制Servelt DispatcherServlet捕獲明郭;
- DispatcherServlet對(duì)請(qǐng)求URL進(jìn)行解析买窟,得到請(qǐng)求資源標(biāo)識(shí)符(URI)。然后根據(jù)該URI薯定,調(diào)用HandlerMapping獲得該Handler配置的所有相關(guān)的對(duì)象(包括Handler對(duì)象以及Handler對(duì)象對(duì)應(yīng)的攔截器)始绍,最后以HandlerExecutionChain對(duì)象的形式返回;
- DispatcherServlet 根據(jù)獲得的Handler话侄,選擇一個(gè)合適的HandlerAdapter亏推。(附注:如果成功獲得HandlerAdapter后,此時(shí)將開始執(zhí)行攔截器的preHandler(...)方法)
- 提取Request中的模型數(shù)據(jù)年堆,填充Handler入?yún)⑼毯迹_始執(zhí)行Handler(Controller)。 在填充Handler的入?yún)⑦^程中嘀韧,根據(jù)你的配置篇亭,Spring將幫你做一些額外的工作:
HttpMessageConveter: 將請(qǐng)求消息(如Json、xml等數(shù)據(jù))轉(zhuǎn)換成一個(gè)對(duì)象锄贷,將對(duì)象轉(zhuǎn)換為指定的響應(yīng)信息
數(shù)據(jù)轉(zhuǎn)換:對(duì)請(qǐng)求消息進(jìn)行數(shù)據(jù)轉(zhuǎn)換译蒂。如String轉(zhuǎn)換成Integer曼月、Double等
數(shù)據(jù)根式化:對(duì)請(qǐng)求消息進(jìn)行數(shù)據(jù)格式化。 如將字符串轉(zhuǎn)換成格式化數(shù)字或格式化日期等
數(shù)據(jù)驗(yàn)證: 驗(yàn)證數(shù)據(jù)的有效性(長(zhǎng)度柔昼、格式等)哑芹,驗(yàn)證結(jié)果存儲(chǔ)到BindingResult或Error中 - Handler執(zhí)行完成后,向DispatcherServlet 返回一個(gè)ModelAndView對(duì)象捕透;
- 根據(jù)返回的ModelAndView聪姿,選擇一個(gè)適合的ViewResolver(必須是已經(jīng)注冊(cè)到Spring容器中的ViewResolver)返回給DispatcherServlet ;
- ViewResolver 結(jié)合Model和View乙嘀,來渲染視圖
- 將渲染結(jié)果返回給客戶端末购。
Spring如何處理線程并發(fā)
Spring使用ThreadLocal解決線程安全問題
我們知道在一般情況下,只有無狀態(tài)的Bean才可以在多線程環(huán)境下共享虎谢,在Spring中盟榴,絕大部分Bean都可以聲明為singleton作用域。就是因?yàn)镾pring對(duì)一些Bean(如RequestContextHolder婴噩、TransactionSynchronizationManager擎场、LocaleContextHolder等)中非線程安全狀態(tài)采用ThreadLocal進(jìn)行處理,讓它們也成為線程安全的狀態(tài)几莽,因?yàn)橛袪顟B(tài)的Bean就可以在多線程中共享了迅办。
ThreadLocal和線程同步機(jī)制都是為了解決多線程中相同變量的訪問沖突問題。
在同步機(jī)制中章蚣,通過對(duì)象的鎖機(jī)制保證同一時(shí)間只有一個(gè)線程訪問變量站欺。這時(shí)該變量是多個(gè)線程共享的,使用同步機(jī)制要求程序慎密地分析什么時(shí)候?qū)ψ兞窟M(jìn)行讀寫纤垂,什么時(shí)候需要鎖定某個(gè)對(duì)象镊绪,什么時(shí)候釋放對(duì)象鎖等繁雜的問題,程序設(shè)計(jì)和編寫難度相對(duì)較大洒忧。
而ThreadLocal則從另一個(gè)角度來解決多線程的并發(fā)訪問。ThreadLocal會(huì)為每一個(gè)線程提供一個(gè)獨(dú)立的變量副本够颠,從而隔離了多個(gè)線程對(duì)數(shù)據(jù)的訪問沖突熙侍。因?yàn)槊恳粋€(gè)線程都擁有自己的變量副本,從而也就沒有必要對(duì)該變量進(jìn)行同步了履磨。ThreadLocal提供了線程安全的共享對(duì)象蛉抓,在編寫多線程代碼時(shí),可以把不安全的變量封裝進(jìn)ThreadLocal剃诅。
由于ThreadLocal中可以持有任何類型的對(duì)象巷送,低版本JDK所提供的get()返回的是Object對(duì)象,需要強(qiáng)制類型轉(zhuǎn)換矛辕。但JDK5.0通過泛型很好的解決了這個(gè)問題笑跛,在一定程度地簡(jiǎn)化ThreadLocal的使用付魔。
概括起來說,對(duì)于多線程資源共享的問題飞蹂,同步機(jī)制采用了“以時(shí)間換空間”的方式几苍,而ThreadLocal采用了“以空間換時(shí)間”的方式。前者僅提供一份變量陈哑,讓不同的線程排隊(duì)訪問妻坝,而后者為每一個(gè)線程都提供了一份變量,因此可以同時(shí)訪問而互不影響惊窖。
Spring的事物管理
事務(wù)就是對(duì)一系列的數(shù)據(jù)庫(kù)操作(比如插入多條數(shù)據(jù))進(jìn)行統(tǒng)一的提交或回滾操作刽宪,如果插入成功,那么一起成功界酒,如果中間有一條出現(xiàn)異常圣拄,那么回滾之前的所有操作。這樣可以防止出現(xiàn)臟數(shù)據(jù)盾计,防止數(shù)據(jù)庫(kù)數(shù)據(jù)出現(xiàn)問題售担。
開發(fā)中為了避免這種情況一般都會(huì)進(jìn)行事務(wù)管理。Spring中也有自己的事務(wù)管理機(jī)制署辉,一般是使用TransactionMananger進(jìn)行管 理族铆,可以通過Spring的注入來完成此功能。spring提供了幾個(gè)關(guān)于事務(wù)處理的類:
TransactionDefinition //事務(wù)屬性定義
TranscationStatus //代表了當(dāng)前的事務(wù)哭尝,可以提交哥攘,回滾。
PlatformTransactionManager這個(gè)是spring提供的用于管理事務(wù)的基礎(chǔ)接口材鹦,其下有一個(gè)實(shí)現(xiàn)的抽象類 AbstractPlatformTransactionManager,我們使用的事務(wù)管理類例如 DataSourceTransactionManager等都是這個(gè)類的子類逝淹。