Spring知識點總結
1. 簡介一下Spring框架。
答:Spring框架是一個開源的容器性質的輕量級框架。主要有三大特點:容器、IOC(控制反轉)、AOP(面向切面編程)。
2. Spring框架有哪些優點?談談你的看法。
答:Spring框架主要有三大優點:
(1) 容器。Spring框架是一個容器,能夠管理項目中的所有對象。
(2) IOC(控制反轉)。Spring將創建對象的方式反轉了,從程序員自己創建反轉給了程序。
(3) AOP(面向切面)。面向切面編程,簡而言之,就是將縱向重複的代碼橫向抽取出來。Spring框架應用了面向切面的思想,主要體現在爲容器中管理的對象生成動態代理對象。
3. 什麼是IOC?
答:IOC:控制反轉,指得是將對象的創建權反轉給Spring。作用是實現了程序的解耦合。
4. 什麼是DI?
答:DI:依賴注入,需要有IOC環境,在Spring創建Bean對象時,動態的將依賴對象注入到Bean對象中去。依賴注入最大的好處就是解耦合。
5. 你對Spring框架中的BeanFactory接口和ApplicationContext接口有什麼理解?二者有什麼區別?
答:BeanFactory接口是Spring框架的頂層接口,是最原始的接口,通過new (BeanFactory的實現類)來啓動Spring容器時,並不會創建Spring容器裏面的對象,只有在每次通過getBean()獲得對象時纔會創建。
ApplicationContext接口是用來替代BeanFactory接口的,通過new (ApplicationContext接口的實現類)ClassPathXmlApplicationContext來啓動Spring容器時,就會創建容器中配置的所有對象。
6. Spring中的工廠容器有哪兩個,它們的區別是什麼?
答:BeanFactory和ApplicationContext。
BeanFactory接口是Spring框架的頂層接口,是最原始的接口,ApplicationContext是對BeanFactory擴展,BeanFactory在第一次getBean時纔會初始化Bean, ApplicationContext是會在加載配置文件時初始化Bean。
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); IHelloService helloService = (IHelloService) beanFactory.getBean("helloService"); helloService.sayHello(); |
我們剛開始學習用spring創建Bean對象的時候,最先學的是通過配置<Bean>標籤的形式,這一塊有很多的知識點需要我們掌握。
7. 談談你對Spring容器中Bean標籤的理解。
答:Bean標籤用來描述Spring容器管理的對象。
假如有一個User對象,需要交給Spring容器來管理,這樣就需要在Spring容器的主配置文件中通過Bean標籤來描述該對象。Bean標籤常見的屬性有以下幾個:
name屬性:給被管理的對象起個名稱,獲得對象時要根據該名稱來獲得。
class屬性:被管理對象的完整類名。
scope屬性:scope屬性常見的有兩個屬性值,singleton和prototype,這兩個屬性值用 來指定創建對象時是單例還是多例,默認爲singleton(單例),但在整合整合struts2 時,ActionBean必須配置爲多例的.
8. Spring通過配置<bean>標籤來生成Bean對象有哪三種方式?
答:空參構造方式、靜態工廠方式和實例工廠方式。一般都只會用空參構造方式。如下:
<bean id="bean1" class="cn.itcast.spring.b_instance.Bean1"></bean> |
9. Spring框架中屬性注入有哪幾種方式:
答:Spring中的輸入注入方式包括set方法注入、構造函數注入、p名稱空間注入、spel注入,除此之外,還包括複雜方式注入,如數組、List、Map、Properties等屬性的注入。
10. 簡述一下bean的生命週期?
答:bean的生命週期包括bean的定義、bean的初始化、bean的調用和bean的銷燬。
在配置文件裏面通過<bean></bean>來完成bean的定義,通過配置init-method屬性來完成bean的初始化,通過得到bean的實例對象來完成bean的調用,通過配置destory-method屬性來完成bean的銷燬。
11. 簡述一下bean的作用域?
答:bean有5種作用域,分別是singleton(單例,默認)、prototype(默認)、request、session、globalSession。
singleton 當一個bean的作用域爲singleton, 那麼Spring IoC容器中只會存在一個共享的bean實例,並且所有對bean的請求,只要id與該bean定義相匹配,則只會返回bean的同一實例。 prototype Prototype作用域的bean會導致在每次對該bean請求(將其注入到另一個bean中,或者以程序的方式調用容器的getBean() 方法)時都會創建一個新的bean實例。根據經驗,對所有有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用 singleton作用域 request 在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例, 它們依據某個bean定義創建而成。該作用 域僅在基於web的Spring ApplicationContext情形下有效。 session 在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring ApplicationContext情形下有效。 global session 在一個全局的HTTP Session中,一個bean定義對應一個實例。典型情況下,僅在使用portlet context的時候有效。該作用域僅在基於 web的Spring ApplicationContext情形下有效。 |
以上講了Spring容器的常見配置,比如向Spring容器中註冊一個對象,需要在Spring的主配置文件中用Bean標籤來描述該對象,在實際開發中,一個項目中會有特別多的對象,如果都用Bean標籤來配置,未免太過麻煩了。基於此,Spring容器爲我們提供了註解的概念,用註解來代替配置。
如何使用Spring中的註解?
在使用註解之前,要先在spring的主配置文件中通過Context:component-scan標籤來開啓使用註解的開關。
12. 用註解將對象註冊到Spring容器當中,有幾種註解方式?它們有什麼區別嗎?
答:4種。分別是:@Component()、@Service()、@Controller()、@Respository()。
Spring框架最早出現的只有@Component()註解,但如果所有的對象都使用同一個註解,很難區分對象究竟屬於哪一層架構。基於此,Spring又推出了@Service()、@Controller()、@Respository()三種註解,用於區分對象屬於哪一層架構。但4種註解方式從功能上來說沒有任何區別。
13. Spring框架中,什麼註解可以用來指定對象的作用範圍?
答:@Scope(scopeName=”singleton”)。
14. 如何用註解的方式來完成屬性注入?
答:按類型分可以分爲值類型注入和引用類型注入。
值類型注入可以通過@Value()註解來完成,該註解既可以聲明在屬性上,也可以聲明在方法上,建議聲明在方法上,但是更多的人會聲明在屬性上,因爲更方便。
引用類型注入可以通過三種註解方式來完成,分別爲:@Autowired、@Autowired和@Qualifier()二者結合、@Resource()。建議使用@Resource(),但是一般我都會用@Autowired。
按註解的方式來完成屬性注入要分兩種情況,一種是值類型注入,一種是引用類型注入。如果是值類型注入,用@Value()註解;如果是引用類型注入,用@Autowired註解。
Spring中的AOP
1. 談談你對AOP的理解。
答:AOP,面向切面編程,是對OOP(面向對象編程)的補充和完善。簡單來講就是將縱向重複的代碼,橫向抽取出來。
很明顯的一個體現就是在Filter過濾器中。在沒有Filter之前,解決servlet的亂碼問題是很複雜的,每次在接收請求之前,都要寫句代碼來解決亂碼問題,即:request.setCharacterEncoding(“UTF-8”),只要寫一個servlet,就是寫這句代碼來解決亂碼問題。直到有一天,Filter出現了。我們把解決亂碼的那句代碼放到Filter中去,從此在servlet中,就再也不用重複寫那句代碼了。從架構上來說,Filter解決亂碼的事架在了所有的servlet上,這樣一來,切面就形成了。
面向切面編程的思想,還有一個直接的體現就是在攔截器中。(後面待補充)
2. Spring中的AOP思想靠什麼來體現的呢?
答:Spring中的AOP思想體現在能夠爲容器中管理的對象生成動態代理對象。
以前我們要使用動態代理,我們需要自己調用下面的方法:
Proxy.newProxyInstance(xx,xx,xx);
生成代理對象。
Spring能幫助我們生成代理對象。
爲什麼叫springAOP呢?
Spring可以爲所有service層的類生成動態代理對象,告訴spring,爲每一個service層的類裏面的方法添加管理事務的代碼,spring一聽,是!這樣我們叫可以只寫一遍管理事務的代碼,就爲所有的service就都加上了管理事務的代碼。這樣一來,aop思想就體現出來了。
SpringAOP的本質就是幫我們生成動態代理對象。
Spring實現AOP的原理?
答:JDK動態代理和cglib代理。
JDK動態代理有缺陷,就是被代理對象必須實現接口才能產生代理對象,如果沒有接口,就不能使用動態代理技術。我們用spring容器來實現動態代理,假如要管理的對象沒有實現接口,那麼就不能產生代理對象了。爲了讓所有的對象都能產生動態代理對象,Spring又融入了第三方代理技術cglib代理。Cglib可以對任何類生成代理對象,它的原理是對目標對象進行繼承代理,如果目標對象被final修飾,那麼該類無法被cglib代理。
那麼Spring到底使用的是JDK代理,還是cglib代理呢?
答:混合使用。如果被代理對象實現了接口,就優先使用JDK代理,如果沒有實現接口,就用用cglib代理。
3. aop名詞學習
Aspect(切面):通知和切入點的結合。在SpringAOP中,切面通過帶有@Aspect註解的類實現。
Joinpoint(連接點):目標對象中,所有可以增強的方法
Pointcut(切入點):目標對象中,已經增強的方法。
Advice(通知/增強):增強的代碼
Target(目標對象):被代理對象
Weaving(織入):將通知應用到切入點的過程
Proxy(代理):將通知織入目標對象之後,形成代理對象
4. Spring切面可以應用5種類型的通知,哪5種?
答:前置通知(Before)、後置通知(After,在方法完成之後調用通知,無論方法執行是否成功)、後置通知(After-returning,在方法成功執行之後調用通知)、異常通知(After-throwing,在方法拋出異常後調用通知)、環繞通知(Around,在目標方法之前之後都調用)。
5. Spring中應用aop,需要哪些步驟?
答:(1)導包
(2)準備目標對象
(3)準備通知
(4)將通知織入目標對象中
Spring中配置aop實際上主要配的是第四步——將通知織入目標對象中。有兩種方式,一種是xml配置方式,一種是註解配置方式。
先看xml配置方式:
再看註解配置方式:
Spring AOP的實現方式有哪些?
答:1、經典的基於代理的AOP:使用Java代碼實現,編寫Advice、PointCut,然後提供給Advisor使用。開啓自動代理後,即可在applicationContext中獲得增強後的bean。
2、@AspectJ註解驅動的切面:基於註解的開發(推薦使用),在項目中需要開啓AOP自動代理<aop:aspectj-autoproxy/>。
3、XML Schema方式:需要實現相應的增強接口,如BeforeAdvice、AfterAdvice等。然後利用一下配置如:
ofo面試題:aop機制,實現,具體怎樣使用,具體到標籤?
答: AOP,面向切面編程,是對OOP(面向對象編程)的補充和完善,簡單來講就是將縱向重複的代碼,橫向抽取出來。最明顯的體現就是過濾器和攔截器的使用。
Spring實現AOP的本質是動態代理,Spring採用兩種動態代理的方式,分別是JDK動態代理和cglib動態代理。JDK動態代理的被代理對象必須實現接口,而cglib動態代理的被代理對象原則上可以是任何類,cglib實現動態代理的原理是對被代理對象進行繼承,重寫被代理對象中所有的方法,所以被代理對象不能被final修飾。
Spring操作AOP,具體可分爲4步。1.導包;2,準備目標對象;3.準備通知;4,將通知織入目標對象。其中2(準備目標對象)和3(準備通知)由java代碼實現,4(將通知織入目標對象)有兩種實現方式,一種是xml配置,一種是註解配置。其中,xml配置用的標籤有<aop:config>、<aop:pointcut>、<aop:aspect>、<aop:before>、<aop:after-returning>、<aop:around>、<aop:after-throwing>、<aop:after>。註解配置用到的註解有:@Aspect、@Pointcut、@Before、@AfterReturning、@Around、@AfterThrowing、@After。
Spring中的事務管理
1. 簡單介紹一下Spring中的事務管理。
答:事務就是對一系列的數據庫操作(比如插入多條數據)進行統一的提交或回滾操作,如果插入成功,那麼一起成功,如果中間有一條出現異常,那麼回滾之前的所有操作。這樣可以防止出現髒數據,防止數據庫數據出現問題。
現實世界中最常見的事務例子可能就是轉賬了。
2. 事務的4個特性?
答:ACID。
原子性(Atomic):事務是由一個或多個活動所組成的一個工作單元。原子確保事務中的所有操作全部發生或全部不發生。如果所有的活動都成功了,事務也就成功了。如果任意一個活動失敗了,整個事務也失敗並回滾。
一致性(Consistent):一旦事務完成(不管成功還是失敗),系統必須確保它所建模的業務處於一致的狀態。現實的數據不應該被損壞。
隔離性(Isolated):事務允許多個用戶對相同的數據進行操作,每個用戶的操作不會與其他用戶糾纏在一起。因此,事務應該被彼此隔離,避免發生同步讀寫相同數據的事情(注意的是,隔離性往往涉及到鎖定數據庫中的行或表)。
持久性(Durable):一旦事務完成,事務的結果應該持久化,這樣就能從任何的系統崩潰中恢復過來。這一般會涉及將結果存儲到數據庫或其他形式的持久化存儲中。
3. 在Spring的核心配置文件applicationContext.xml中配置事務,主要配置三大方面:事務管理器、事務通知和定義事務性切面。
代碼如下:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <!-- 事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 數據源 --> <property name="dataSource" ref="dataSource" /> </bean> <!-- 事務通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 傳播行爲 --> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <!-- 定義事務性切面 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.e3mall.service..*.*(..))" /> </aop:config> </beans> |
4. 事務管理器
Spring管理事務有多種方式,但無論選擇將事務編碼到Bean中還是將選擇其定義爲切面,你都需要使用spring事務管理器與平臺相關的事務進行交互。讓我們看一下Spring的事務管理器能如何幫你避免直接與平臺相關的實現打交道?Spring並不直接管理事務,而是提供了多種事務管理器,每個事務管理器都會充當某一特定平臺的事務實現的門面,這使得門戶在Spring中使用事務時,幾乎不用關注實際的事務實現是什麼。
操作事務的方法一般就三種:開啓事務、提交事務、回滾事務。針對這三個方法,JDBC、Hibernate、Mybatis等都有不同的實現方式。因爲在不同平臺、操作事務的代碼各不相同。爲此,Spring提供了一個接口PlatformTransactionManager,針對不同的操作平臺提供不同的實現類。比方說,如果是JDBC和iBatis,實現類是DataSourceTransactionManager,如果是Hibernate,實現類是HibernateTransactionManager。不同的實現類就是不同的事務管理器,爲了使用事務管理器,你需要將其聲明在應用程序上下文中。
<!-- 事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 數據源 --> <property name="dataSource" ref="dataSource" /> </bean> |
如果在應用程序中你直接使用JDBC/iBatis來進行持久化,DataSourceTransactionManager會爲你處理事務邊界。爲了使用DataSourceTransactionManager,你需要使用如下的XML將其裝配到應用程序的上下文定義中:
如果應用程序的持久化是通過Hibernate實現的,那麼你需要使用HibernateTransactionManager,你需要使用如下的XML將其裝配到應用程序的上下文定義中:
<!-- 事務管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <!-- 數據源 --> <property name="dataSource" ref="dataSource" /> </bean> |
當配置好事務管理器之後,在spring中具體配置事務時,又有兩種選擇:一種是編碼事務(瞭解),一種是聲明式事務。聲明式事務是通過事務屬性來定義的,具體的說,是通過傳播行爲、隔離級別、只讀提示、事務超時及回滾規則來進行定義的。
5. 事務的傳播行爲指什麼?
答:在業務(service)方法之間平行調用時,如何來處理事務的問題。
6. Spring中定義事務傳播行爲的屬性有幾種,分別是什麼?
答:7種。分別是REQUIRED、REQUIRES_NEW、SUPPORTS、NOT_SUPPORTED、MANDATORY、NESTED、NEVER。我們常用的是propagation=”REQUIRED”,默認的就是REQUIRED,指得是支持當前事務,如果不存在,就新建一個(默認),所以這個屬性不用配置。其餘6個屬性幾乎不用。
7. 事務中可能會出現的併發問題有哪些?
答:髒讀、不可重複讀、幻讀。解決併發問題的方法就是設置隔離級別。
什麼是髒讀?讀到了某一個正在操作但還沒有提交的數據,這樣讀到的數據很可能不是最終確定的數據,很可能那個人還回滾了。
什麼是不可重複讀?兩次連續的讀取,數據不一致,可能是有人在你第一次讀完之後將數據修改並提交了,導致你再讀取的時候,數據和第一次讀取的不一致,不知道該用哪一次。
什麼是幻讀?往往是針對的整表的操作,比如經理讓你將整張user表都刪掉,結果在你刪的期間,有人往這張表中加了一條記錄,當你刪完之後,你覺着數據庫中沒有這張表了,但是一查,這張表中還有一條數據,這個時候你覺着自己產生了幻覺,怎麼還有一條呢?明明都已經刪了。這就叫幻讀。
在理想情況下,事務之間是完全隔離的,從而可以防止這些問題發生,但是完全隔離會導致性能問題,因爲它通常會涉及鎖定數據庫中的記錄,侵佔性的鎖定會阻礙併發性,要求事務互相等待以完成各自的工作。
考慮到完全的隔離會導致性能問題,而且並不是所有的應用程序都需要完全的隔離,所以有時應用程序需要在事務隔離上有一定的靈活性。因此就會有各種隔離級別。
8. 事務中有幾種隔離級別呢?
答:4種。讀未提交(uncommitted)、讀已提交(committed)、可重複讀(repeatable_read)、串行化(serializable)。
讀未提交(uncommitted):允許讀取尚未提交的數據變更。可能會導致髒讀、幻讀或不可重複讀。
讀已提交(committed):允許讀取併發事務已經提交的數據。可以阻止髒讀、但是幻讀或不可重複讀仍有可能發生。
可重複讀(repeatable_read):可以阻止髒讀和不可重複讀,但可能會導致幻讀。
串行化(serializable):完全服從ACID的隔離級別,確保阻止髒讀、不可重複讀以及幻讀。這是最慢的事務隔離級別,因爲它通常是通過完全鎖定事務相關的數據庫表來實現的。
9. 聲明式事務的第三個屬性是隻讀。read-only=”true” 或者 read-only=”false”,在定義查詢方法時,通常設置爲只讀。
10. 事務超時和回滾規則 這兩個屬性幾乎不用,用到的時候再查資料。
11. 基於在5大事務屬性,就可以在XML中定義事務了。代碼如下:
<!-- 事務通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 傳播行爲 --> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> |
<tx:advice>只是定義了AOP通知,用於把事務邊界通知給方法,但是這只是事務通知,而不是完整的事務性切面。我們在<tx:advice>中沒有聲明哪些Bean應該被通知——我們需要一個切點來做這件事,爲了完整定義事務切面,我們必須定義一個通知器(advisor)。這就涉及aop命名空間了。以下的XML定義了一個通知器,它使用txAdvice通知所有實現SpitterService接口的Bean,代碼如下:
<!-- 定義事務性切面 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.e3mall.service..*.*(..))" /> </aop:config> |
<tx:advice>配置元素極大地簡化了Spring聲明式事務所需要的XML,如果我告訴你它甚至可以進一步簡化,你會感受如何呢?如果我再告訴你,你只需要在Spring上下文中添加一行XML,即可聲明事務,你的感受如何呢?這就是用註解的方式來配置事務。
Spring整合SSM
使用Spring整合SSM框架,需要配置哪些東西?簡單說一下。
答:Spring整合Dao,要配置數據庫啓動,配置SqlSessionFactory,配置Mapper動態代理。
Spring整合Service,要配置包掃描器(開啓註解驅動),要配置事務管理(事務管理器,事務通知,事務切面)。
Spring整合Web,要配置包掃描器(掃描Controller),配置處理器映射器和處理器適配器(採用註解驅動的方法),配置視圖解析器。
在web層,要加載Spring容器,並且要配置一個springMVC的前端控制器。