提及Spring,咱們就挑重點能理解的來講,由於源碼我暫時着實看不懂html
說到Spring,就必須提到 IOC DI AOP這三個關鍵詞,固然也是面試常問,通常讓你介紹Spring,都是從這裏開始java
今天我就對其進行淺層面(涉及一點源碼)的對其複習一波:web
之前咱們使用對象,都是經過手動 new的方式建立對象,當咱們使用了Spring後,咱們將對象的建立權利反轉給Spring,由Spring容器 統一管理對象的建立和依賴關係以及生命週期等,說到IOC就必須說到IOC容器,其本質就是建立類的實列的工廠 ,而且對類的實列進行管理 ,下面有重點介紹面試
1.動態的給一個對象向其提供它所須要依賴的其餘對象或屬性有樹洞和自動之分,如今通常都是註解開發,spring
2.手動裝配就是在<bean>標籤中經過<property>注入,這種須要該屬性提供set方法數據庫
3.自動裝配經過@Autowrite 和 @Resource註解,進行裝配express
@Autowrite : 根據類型查找實列(單列) ,並賦值完成注入;編程
@Resource : 根據Bean的名稱查找獲取實列,完成裝配;服務器
aop能夠說是Spring中的和超級重點了,使用技術:反射、代理,代理包括jdk代理和cglib反向代理;併發
簡單理解就是針對目標對象進行動態代理,橫向加強JavaBean
AOP術語:
target:目標類,須要被代理的類。userService;
Joinpoint(鏈接點):所謂鏈接點是指那些可能被攔截到的方法。例如:全部的方法;
PointCut 切入點:已經被加強的鏈接點。例如:addUser();
advice 通知/加強,加強代碼。例如:after、before
Weaving(織入) : 是指把加強advice應用到目標對象target來建立新的代理對象proxy的過程;
proxy : 代理類
Aspect(切面) : 是切入點pointcut和通知advice的結合
在理筆記以前,咱們先弄清楚幾個概念:web服務器 、web容器、spring容器;
1.web服務器 : 也就是servlet容器,好比咱們經常使用的 Tomcat 還有Jetty Jboss等;
2.web容器 : 即Servlet上下文(Application) ServletContext,Servlet三大做用域中生命週期最長的那個
3.Spring容器: 也叫 IOC容器,Spring學習的重點,即Spring上下文 SpringContext
所謂的IOC容器:指的是Bean工廠裏面的一個Map儲存結構(K: bean標籤中的id屬性值 --V: 對象的實列對象)
Spring中的工廠早起就BeanFactory,Spring容器頂層接口,採用的事延遲加載機制,如今用的是ApplicationContext,對註冊爲單列的Bean在讀取配置文件是就是加載配置穩當,ApplicationContext是繼承BeanFactory的一個接口,兩個接口最下層作事情的都是DefaultListableBeanFactory
初始化過程:
1.web服務器啓動的時候會讀取web.xml,啓動咱們配置的ContextLoaderListener監聽器
2.服務器啓動後建立servlet上下文的時候會觸發ContextLoaderLister監聽器的contextInitialized()方法;
3.contextInitialized()方法中調用initWebApplicationContext()方法建立Spring容器和生產Bean對象(反射);
4.initWebApplicationContext經過createWebApplicationContext()方法會建立WebApplicationContext;
5.WebApplicationContext是一個接口,這裏建立的是它的默認實現類:XmlWebApplicationContext(真正的容器)
6.經過configureAndRefreshWebApplicationContext()方法加載Spring的配置文件,建立Bean
7.經過servletContext.setAttribute()方法,將spring容器context掛載到ServletContext 這個web容器上下文中
大體以下:
說明:(跟着源碼能夠參考參考,我暫時也沒弄明白,先讀讀有個印象)
1.ResourceLoader加載Spring配置信息,並使用Resource表示這個配置文件的資源
2.BeanDefinitionReader讀取Resource所指向的配置文件資源,解析文件中每個<bean>標籤,生成對應的BeanDefinition對象,並保 存到BeanDefinitionRegistry中
3.容器掃描BeanDefinitionRegistry中的BeanDefinition,使用Java的反射機制自動識別出Bean工廠後處理後器(實現BeanFactoryPostProcessor接口)的Bean,而後調用這些Bean工廠後處理器對4.BeanDefinitionRegistry中的BeanDefinition進行加工處理。主要完成如下兩項工做
1)對使用到佔位符的<bean>元素標籤進行解析,獲得最終的配置值,這意味對一些半成品式的BeanDefinition對象進行加工處理並獲得成品的BeanDefinition對象;
2)對BeanDefinitionRegistry中的BeanDefinition進行掃描,經過Java反射機制找出全部屬性編輯器的Bean(實現java.beans.PropertyEditor接口的Bean),並自動將它們註冊到Spring容器的屬性編輯器註冊表中(PropertyEditorRegistry);
5.Spring容器從BeanDefinitionRegistry中取出加工後的BeanDefinition,並調用InstantiationStrategy着手進行Bean實例化的工做;
6.在實例化Bean時,Spring容器使用BeanWrapper對Bean進行封裝,BeanWrapper提供了不少以Java反射機制操做Bean的方法,它將結合該Bean的BeanDefinition以及容器中屬性編輯器,完成Bean屬性的設置工做;
7.利用容器中註冊的Bean後處理器(實現BeanPostProcessor接口的Bean)對已經完成屬性設置工做的Bean進行後續加工,直接裝配出一個準備就緒的Bean。
8.Spring容器確實堪稱一部設計精密的機器,其內部擁有衆多的組件和裝置。Spring的高明之處在於,它使用衆多接口描繪出了全部裝置的藍圖,構建好Spring的骨架,繼而經過繼承體系層層推演,不斷豐富,最終讓Spring成爲有血有肉的完整的框架。因此查看Spring框架的源碼時,有兩條清晰可見的脈絡:
1)接口層描述了容器的重要組件及組件間的協做關係;
2)繼承體系逐步實現組件的各項功能。
接口層清晰地勾勒出Spring框架的高層功能,框架脈絡呼之欲出。有了接口層抽象的描述後,不但Spring本身能夠提供具體的實現,任何第三方組織也能夠提供不一樣實現, 能夠說Spring完善的接口層使框架的擴展性獲得了很好的保證。縱向繼承體系的逐步擴展,分步驟地實現框架的功能,這種實現方案保證了框架功能不會堆積在某些類的身上,形成太重的代碼邏輯負載,框架的複雜度被完美地分解開了。
Spring組件按其所承擔的角色能夠劃分爲兩類:
1)物料組件:Resource、BeanDefinition、PropertyEditor以及最終的Bean等,它們是加工流程中被加工、被消費的組件,就像流水線上被加工的物料;
2)加工設備組件:ResourceLoader、BeanDefinitionReader、BeanFactoryPostProcessor、InstantiationStrategy以及BeanWrapper等組件像是流水線上不一樣環節的加工設備,對物料組件進行加工處理。
在配置文件經過<bean>標籤配置,該標籤最後會加工成一個BeanDefition對象 ( 上面說到的用來描述對象信息的對象)
列子太普通,就是經過ClassPathXmlApplicationContext讀取配置文件,獲取一個容器ApplicationContext引用
在容器中能夠經過兩種方式獲取對象 傳入.class根據類型獲取 傳入<bean>標籤的id獲取亦可
在這個過程當中,實列化bean的幾種方式:
( 默認 ) 使用無參構造函數實列化,若是沒有無參構造,建立失敗
其次就是靜態工廠和實列工廠
構造函數注入: 該實列中有個有參構造方法 分別對 id username 進行賦值 和下面這個配置文件一一對應生效
<bean id="userService" class="com.test.di.service.userServiceImpl">
<constructor-arg name="id" value="1" />
<constructor-arg name="username" value="張三" />
<bean>
set方法注入: 手動裝配 / 自動裝配
手動裝配: 經過 <property name="" value=""> 須要在須要的類中給出 set方法才行
自動裝配:@AutoWired 和 @Resource
還有一個P名稱看見注入數據,本質上仍是set方法,不怎麼用,不作筆記
依賴注入不一樣類型的屬性:
簡單類型 : value | 引用類型 : ref | 集合比較多,須要時即時瞭解亦可
@Component : 至關於一個<bean>標籤
value:指定bean的id,若是不聲明,默認類名首字母小寫
@Controller (表現層) 、@Service (業務層) 、@Repository (持久層)
這三個註解是@Component註解的衍生註解
@AutoWired : 默認按照類型裝配
@Qualifier : 在@AutoWired註解基礎上,再按照Bean的id注入 ( 必須搭配使用)
@Resource : 經過名字進行裝配,不屬於Spring,是J2EE的註解
若是沒有匹配上,其次選擇按照類型裝配
@Value :給基本類型和String類型注入值,也可使用佔位符的方式獲取配置文件中的值 好比:
@Value("username") // username 是properties文件中的key
@Scope : 改變做用域分範圍,知道 singleton和 prototype便可
SSM的使用XMl的整合,素有配置地獄的稱號,能夠純註解開發將取代配置文件的編寫,採用註解的方式配置
@Configuration :用於申明當前類爲一個配置類,
@Bean 標註在方法上,該方法返回什麼對象,就把該對象裝配到Spring容器,通常用於配置非自定義的bean
該註解默認爲單列做用域,可經過@Scope註解從新指定做用域
@ComponentScan : 至關於配置文件中的 context:component-scan 標籤,掃描包下註解的做用
@PropertySource : 加載propeties配置文件,編寫在類上 至關於context:property-placeholder標籤
列如: @PropertySource(「classpath:jdbc.properties」)
@Impport : 用來組合多個配置類,value:指定其餘配置類的字節碼文件
列如 @Import({ JdbcConfig.class})
IOCy原理部分理解:
什麼是IOC
聲明式Spring容器(IOC容器)
如何建立Spring容器
Spring容器如何初始化
DI原理部分理解:
什麼是依賴
什麼事DI(依賴注入)
何時進行依賴注入
DI 的方式有哪些
不一樣數據類型如歌進行注入
1. 依賴: spring-test 包
2. 經過RunWith( SpringJunit4ClassRunner ) ,指定Spring提供的單元測試的運行器 : SpringJunit4ClassRunner
3. 經過@ContextConfiguration註解,指定Spring運行器須要的配置文件路徑
如:@ContextConfiguration ( locations="classpath:applicationContext.xml") 讀取配置文件
@ContextConfiguration ( classes=SpringConfiguration.class) 讀取配置類,純註解開發模式
4. 經過@AutoWired註解 注入咱們須要的數據
aop 是一種思想,經過預編譯和運行期動態代理的方式實現程序功能的統一維護的一種實現
利用aop能夠對業務邏輯的各個部分進行分割,提升切面的可重用性,咱們打比方一個麪包片就像咱們的一個業務邏輯,咱們能夠在這個麪包片的上面或者下面給它塗上各類醬。在代碼中表現爲:性能檢測、權限驗證、日誌紀錄、事務控制、
Spring AOP 是經過動態代理技術實現,動態代理基於反射設計,動態代理技術的實現有兩種
一種是基於接口的JDK動態代理
一種是基於繼承的CGLIB動態代理,詳細請見:http://www.javashuo.com/article/p-tpgbfhsd-bp.html
spring整合包:spring-sapects包 | aop聯盟:aopalliance包
肯定目前類和通知類,將其交由Spring容器統一管理
配置AOP切面,總體以下:
其中涉及到一個 切入點表達式的知識 :移步這裏 http://www.javashuo.com/article/p-yikvuydj-cc.html
execution([修飾符] 返回值類型 包名.類名.方法名(參數))
經過上面的配置咱們能夠看見 <aop:aspect ref="MyAdvice"> 咱們將一個類定義爲 通知/加強類
其下有:照着輪子造就OK
以上就是基於Xml的方法,下面說說基於註解的方式:
最後再補充一點,使用純註解的方式:
選擇一個類做爲配置類,在上面開啓相應的註解:
在測試的時候,只須要把讀取配置文件的方式改爲讀取配置類的方式便可:
@ContextConfiguration(classes = MyConfiguration.class) //使用純註解的方式
因爲用的不多不多,通常經常使用持久層框架爲MyBatis或者SpringDataJPA,因此這裏簡單說一下:
IOC4個包(beans core context expression)、AOP2個包(aspects aopalliance)、
C3P0一個包、MySQL驅動包、SpringJDBC2個包(tx jdbc)、Junit測試包
Dao層實現類繼承 JdbcDaoSupport 並注入DataSource經過 this.getJdbcTemplate()便可
事務回顧幾個特性?各有什麼特色?
隔離性的級別有哪些?致使在事務併發時出現幾個問題?各自有什麼特色?
回憶:原子性 、一致性、隔離性、持久性、
一致性:那轉帳來講,不管A怎麼向B轉帳,他們兩個帳戶的總金額是不會變得
隔離性:當多個請求併發訪問數據庫時,爲每個請求開啓的事務不能被其餘事務所幹擾,要隔離開來
持久性:就是事務一旦提交,數據就會持久化到數據庫,是永久、持久性的
回憶:http://www.javashuo.com/article/p-kqobegbp-dp.html(搬磚的事情就不幹了)
Spring框架事務管理分爲編程式事務和聲明式事務,前者不推薦使用,不作筆記
聲明式事務又分爲Xml方式 和 註解方式,咱們都須要掌握使用
首先咱們說說Xml方式事務的使用:
第一步說明:配置平臺事務管理器,不管是Xml方式仍是註解方式都須要的配置
第二步說明:配置通知,經過其中的屬性,我看能夠看出咱們將平臺事務管理器和transfer()聯繫到了一塊兒,並設置相應的事務傳播行爲
第三步說明:切面配置,肯定通知應用到那些切入點上
再說說基於註解的,這種運用相對簡單,使用普遍:
能夠看出,咱們只須要配置一個 平臺事務管理器,而後經過一個註解開啓註解事務,
在咱們須要開啓的類 或者方法上加上@Transactional便可
總體結構以下: