1、Mybatis
1.1 概念
MyBatis 是一個持久層框架,實現了對JDBC操作的封裝,主要用於簡化JDBC操作中的一些相對繁瑣的步驟,例如參數的映射,結果集的映射等。可以簡單快速地連接和操作數據庫,同時把操作數據庫的結果集封裝為Java對象返回
1.2 Mybatis優點
Mybatis的優點:
(1)Mybatis對JDBC進行封裝,在實際開發中不用花費時間和精力去處理對數據庫連接等的處理;
(2)Mybatis自身支持連接池,也可以配置其他的連接池,如c3p0、druid,提高了程序的效率;
(3)Mybatis是將SQL配置在mapper.xml文件中,當需求發生變更時只修改xml配置文件就可以了,類不需要重新編譯。
(4)執行SQL后返回的ResultSet結果對象,Mybatis會幫我們處理,轉換成Java對象,方便我們對結果的處理。
1.3 Mybatis架構
(1)sqlMapConfig.xml是Mybatis的核心配置文件,通過其中的配置可以生成SqlSessionFactory,也就是SqlSession工廠
(2)基於SqlSessionFactory可以生成SqlSession對象
(3)SqlSession是一個既可以發送SQL去執行,並返回結果,類似於JDBC中的Connection對象,也是Mybatis中至關重要的一個對象。
(4)Executor是SqlSession底層的對象,用於執行SQL語句
(5)MapperStatement對象也是SqlSession底層的對象,用於接收輸入映射(SQL語句中的參數),以及做輸出映射(即將SQL查詢的結果映射成相應的結果)
1.4 底層原理
1、工作原理圖
工作原理解析
mybatis應用程序通過SqlSessionFactoryBuilder從mybatis-config.xml配置文件(也可以用Java文件配置(注解)的方式,需要添加@Configuration)中構建出SqlSessionFactory(SqlSessionFactory是線程安全的);
然后,SqlSessionFactory的實例直接開啟一個SqlSession,再通過SqlSession實例獲得Mapper對象並運行Mapper映射的SQL語句,完成對數據庫的CRUD和事務提交,之后關閉SqlSession。
說明:SqlSession是單線程對象,因為它是非線程安全的,是持久化操作的獨享對象,類似jdbc中的Connection,底層就封裝了jdbc連接。
詳細流程如下
1、加載mybatis全局配置文件(數據源、mapper映射文件等),解析配置文件,MyBatis基於XML配置文件生成Configuration,和一個個MappedStatement(包括了參數映射配置、動態SQL語句、結果映射配置),其對應着<select | update | delete | insert>標簽項。
2、SqlSessionFactoryBuilder通過Configuration對象生成SqlSessionFactory,用來開啟SqlSession。
3、SqlSession對象完成和數據庫的交互:
a、用戶程序調用mybatis接口層api(即Mapper接口中的方法)
b、SqlSession通過調用api的Statement ID找到對應的MappedStatement對象
c、通過Executor(負責動態SQL的生成和查詢緩存的維護)將MappedStatement對象進行解析,sql參數轉化、動態sql拼接,生成jdbc Statement對象
d、JDBC執行sql。
e、借助MappedStatement中的結果映射關系,將返回結果轉化成HashMap、JavaBean等存儲結構並返回。
mybatis層次圖:
1.5 Mybatis緩存
Mybatis的一級緩存是SqlSession級別。第一次執行select時候會發現sqlsession緩存沒有記錄,會去數據庫查找,然后把結果保存到緩存,第二次同等條件查詢下,就會從緩存中查找到結果。另外為了避免臟讀,每次執行更新新增刪除時候會清空當前sqlsession緩存。
二級緩存是namespace級別的。同一個namespace下的搜尋語句共享一個二級緩存。如果開啟了二級緩存,則先從二級緩存中查找,查找不到則委托為SimpleExecutor查找,而它則會先從一級緩存中查找,查找不到則從數據庫查找。
mybaits的二級緩存一般不怎么使用,默認一級緩存是開啟的。
1.6 常見面試題
1、什么是Mybatis?
(1)Mybatis是一個半ORM(對象關系映射)框架,它內部封裝了JDBC,開發時只需要關注SQL語句本身,不需要花費精力去處理加載驅動、創建連接、創建statement等繁雜的過程。程序員直接編寫原生態sql,可以嚴格控制sql執行性能,靈活度高。
(2)MyBatis 可以使用 XML 或注解來配置和映射原生信息,將 POJO映射成數據庫中的記錄,避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
(3)通過xml 文件或注解的方式將要執行的各種 statement 配置起來,並通過java對象和 statement中sql的動態參數進行映射生成最終執行的sql語句,最后由mybatis框架執行sql並將結果映射為java對象並返回。(從執行sql到返回result的過程)。
2、Mybaits的優點:
(1)基於SQL語句編程,相當靈活,不會對應用程序或者數據庫的現有設計造成任何影響,SQL寫在XML里,解除sql與程序代碼的耦合,便於統一管理;提供XML標簽,支持編寫動態SQL語句,並可重用。
(2)與JDBC相比,減少了50%以上的代碼量,消除了JDBC大量冗余的代碼,不需要手動開關連接;
(3)很好的與各種數據庫兼容(因為MyBatis使用JDBC來連接數據庫,所以只要JDBC支持的數據庫MyBatis都支持)。
(4)能夠與Spring很好的集成;
(5)提供映射標簽,支持對象與數據庫的ORM字段關系映射;提供對象關系映射標簽,支持對象關系組件維護。
3、MyBatis框架的缺點:
(1)SQL語句的編寫工作量較大,尤其當字段多、關聯表多時,對開發人員編寫SQL語句的功底有一定要求。
(2)SQL語句依賴於數據庫,導致數據庫移植性差,不能隨意更換數據庫。
4、MyBatis框架適用場合:
(1)MyBatis專注於SQL本身,是一個足夠靈活的DAO層解決方案。
(2)對性能的要求很高,或者需求變化較多的項目,如互聯網項目,MyBatis將是不錯的選擇。
5、MyBatis與Hibernate有哪些不同?
(1)Mybatis和hibernate不同,它不完全是一個ORM框架,因為MyBatis需要程序員自己編寫Sql語句。
(2)Mybatis直接編寫原生態sql,可以嚴格控制sql執行性能,靈活度高,非常適合對關系數據模型要求不高的軟件開發,因為這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。但是靈活的前提是mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件,則需要自定義多套sql映射文件,工作量大。
(3)Hibernate對象/關系映射能力強,數據庫無關性好,對於關系模型要求高的軟件,如果用hibernate開發可以節省很多代碼,提高效率。
6、#{}和${}的區別是什么?
{}是預編譯處理,${}是字符串替換。
Mybatis在處理#{}時,會將sql中的#{}替換為?號,調用PreparedStatement的set方法來賦值;
Mybatis在處理${}時,就是把${}替換成變量的值。
使用#{}可以有效的防止SQL注入,提高系統安全性。
7、當實體類中的屬性名和表中的字段名不一樣怎么辦 ?
第1種: 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致。
第2種: 通過
8、模糊查詢like語句該怎么寫?
SQL語句中的like模糊查詢 select * from table where name like‘%張%’,
但實際開發中經常用到 select * from table where name like concat('%',#{name},'%')
9、通常一個Xml映射文件,都會寫一個Dao接口與之對應,請問,這個Dao接口的工作原理是什么?Dao接口里的方法,參數不同時,方法能重載嗎?
Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法內的參數,就是傳遞給sql的參數。
Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串作為key值,可唯一定位一個MapperStatement。在Mybatis中,每一個
(2)第二種: 使用 @param 注解:
public interface usermapper {
user selectuser(@param(“username”) string username,@param(“hashedpassword”) string hashedpassword);
}
然后,就可以在xml像下面這樣使用(推薦封裝為一個map,作為單個參數傳遞給mapper):
(3)第三種:多個參數封裝成map
try{
//映射文件的命名空間.SQL片段的ID,就可以調用對應的映射文件中的SQL
//由於我們的參數超過了兩個,而方法中只有一個Object參數收集,因此我們使用Map集合來裝載我們的參數
Map<String, Object> map = new HashMap();
map.put("start", start);
map.put("end", end);
return sqlSession.selectList("StudentID.pagination", map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e; }
finally{
MybatisUtil.closeSqlSession();
}
15、Mybatis動態sql有什么用?執行原理?有哪些動態sql?
Mybatis動態sql可以在Xml映射文件內,以標簽的形式編寫動態sql,執行原理是根據表達式的值完成邏輯判斷並動態拼接sql的功能。
Mybatis提供了9種動態sql標簽:trim | where | set | foreach | if | choose | when | otherwise | bind。
16、Xml映射文件中,除了常見的select|insert|updae|delete標簽之外,還有哪些標簽?
答:
17、Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重復?
不同的Xml映射文件,如果配置了namespace,那么id可以重復;如果沒有配置namespace,那么id不能重復;
原因就是namespace+id是作為Map<String, MapperStatement>的key使用的,如果沒有namespace,就剩下id,那么,id重復會導致數據互相覆蓋。有了namespace,自然id就可以重復,namespace不同,namespace+id自然也就不同。
18、為什么說Mybatis是半自動ORM(對象映射模型)映射工具?它與全自動的區別在哪里?
Hibernate屬於全自動ORM映射工具,使用Hibernate查詢關聯對象或者關聯集合對象時,可以根據對象關系模型直接獲取,所以它是全自動的。而Mybatis在查詢關聯對象或關聯集合對象時,需要手動編寫sql來完成,所以,稱之為半自動ORM映射工具。
19、 一對一、一對多的關聯查詢 ?
<!--collection 一對多關聯查詢 -->
<select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">
select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<collection property="student" ofType="com.lcb.user.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
20、MyBatis實現一對一有幾種方式?具體怎么操作的?
有聯合查詢和嵌套查詢,聯合查詢是幾個表聯合查詢,只查詢一次,通過在resultMap里面配置association節點配置一對一的類就可以完成;
嵌套查詢是先查一個表,根據這個表里面的結果的 外鍵id,去再另外一個表里面查詢數據,也是通過association配置,但另外一個表的查詢通過select屬性配置。
22、Mybatis是否支持延遲加載?如果支持,它的實現原理是什么?
答:Mybatis僅支持association關聯對象和collection關聯集合對象的延遲加載,association指的就是一對一,collection指的就是一對多查詢。在Mybatis配置文件中,可以配置是否啟用延遲加載lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB創建目標對象的代理對象,當調用目標方法時,進入攔截器方法,比如調用a.getB().getName(),攔截器invoke()方法發現a.getB()是null值,那么就會單獨發送事先保存好的查詢關聯B對象的sql,把B查詢上來,然后調用a.setB(b),於是a的對象b屬性就有值了,接着完成a.getB().getName()方法的調用。這就是延遲加載的基本原理。
不光是Mybatis,幾乎所有的包括Hibernate,支持延遲加載的原理都是一樣的。
23、Mybatis的一級、二級緩存:
一級緩存: 基於 PerpetualCache 的 HashMap 本地緩存,其存儲作用域為 Session,當 Session flush 或 close 之后,該 Session 中的所有 Cache 就將清空,默認打開一級緩存。
二級緩存與一級緩存其機制相同,默認也是采用 PerpetualCache,HashMap 存儲,不同在於其存儲作用域為 Mapper(Namespace),並且可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啟二級緩存,使用二級緩存屬性類需要實現Serializable序列化接口(可用來保存對象的狀態),可在它的映射文件中配置
24、什么是MyBatis的接口綁定?有哪些實現方式?
接口綁定,就是在MyBatis中任意定義接口,然后把接口里面的方法和SQL語句綁定, 我們直接調用接口方法就可以,這樣比起原來了SqlSession提供的方法我們可以有更加靈活的選擇和設置。
接口綁定有兩種實現方式,一種是通過注解綁定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql語句來綁定;另外一種就是通過xml里面寫SQL來綁定, 在這種情況下,要指定xml映射文件里面的namespace必須為接口的全路徑名。當Sql語句比較簡單時候,用注解綁定, 當SQL語句比較復雜時候,用xml綁定,一般用xml綁定的比較多。
25、使用MyBatis的mapper接口調用時有哪些要求?
①Mapper接口方法名和mapper.xml中定義的每個sql的id相同;
②apper接口方法的輸入參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同;
③Mapper.xml文件中的namespace即是mapper接口的類路徑。
27、簡述Mybatis的插件運行原理,以及如何編寫一個插件。
答:Mybatis僅可以編寫針對ParameterHandler、ResultSetHandler、StatementHandler、Executor這4種接口的插件,Mybatis使用JDK的動態代理,為需要攔截的接口生成代理對象以實現接口方法攔截功能,每當執行這4種接口對象的方法時,就會進入攔截方法,具體就是InvocationHandler的invoke()方法,當然,只會攔截那些你指定需要攔截的方法。
編寫插件:實現Mybatis的Interceptor接口並復寫intercept()方法,然后在給插件編寫注解,指定要攔截哪一個接口的哪些方法即可,記住,別忘了在配置文件中配置你編寫的插件。
2、Spring
2.1 概念
1、Spring是一個開源的輕量級的應用開發框架,其目的是用於簡化企業級應用程序開發,降低開發者的開發難度;
2、Spring提供的IoC和AOP應用,可以將組件的耦合度降至最低(即解耦),便於系統日后的維護和升級;
3、Spring為系統提供了一個整體的解決方案,開發者可以利用它本身提供的功能外,也可以與第三方框架和技術整合應用,可以自由選擇采用哪種技術進行開發。(比如Spring整合SpringMVC、Spring整合MyBatis、Spring整合Struts2、Spring整合Hibernate、Spring整合Quartz[定時任務處理])
2.2 Spring優點
1).方便解耦,簡化開發
通過Spring提供的IoC容器,可以將對象之間的依賴關系交由Spring進行控制,避免硬編碼所造成的過度程序耦合。
2).AOP編程的支持
通過Spring提供的AOP功能,方便進行面向切面的編程,如性能監測、事務管理、日志記錄等。
3).聲明式事務的支持
4).方便集成各種優秀框架
5).降低Java EE API的使用難度,如對JDBC,JavaMail,遠程調用等提供了簡便封裝
2.3 Spring架構
Spring 最初的目標就是要整合一切優秀資源,然后對外提供一個統一的服務。Spring 模塊構建在核心容器之上,核心容器定義了創建、配置和管理 bean 的方式,如下圖所示:
1. 核心容器Spring Core核心容器,提供Spring框架的基本功能。核心容器的主要組件是BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉(IOC)模式,將應用程序的配置和依賴性規范與實際的應用程序代碼分開。
2.Spring Context Spring 上下文,是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。
3.Spring AOP通過配置管理特性,Spring AOP 模塊直接將面向切面的編程功能集成到了 Spring 框架中。可以很容易地使 Spring框架管理的任何對象支持AOP。Spring AOP模塊為基於Spring 的應用程序中的對象提供了事務管理服務。通過使用Spring AOP,就可以將聲明性事務管理集成到應用程序中。
4. Spring DAO JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,並且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。
5.Spring ORM Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關系工具,其中包括JDO、Hibernate和iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。
6.Spring Web Web上下文模塊建立在應用程序上下文模塊之上,為基於Web 的應用程序提供了上下文。所以Spring 框架支持與Jakarta Struts的集成。Web模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作。
7.Spring MVC框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口,MVC 框架變成為高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。
2.4 控制反轉(IOC)
控制反轉,就是指將對象的創建,對象的存儲(map),對象的管理(依賴查找,依賴注入)交給了spring容器。(spring容器是spring中的一個核心模塊,用於管理對象)
只需要將類提前配置在spring配置文件中,就可以將對象的創建交給spring容器,當需要對象時,不需要自己創建,而是直接通過spring獲取即可,省去了new對象,可以降低代碼之間的耦合性。
IOC如何實例化對象?
Spring容器執行過程:
當tomcat服務器啟動時會加載Spring容器的配置文件.當程序解析到Bean標簽時.通過反射機制實例化對象.對象最終保存到了Spring容器自身維護的Map<Id,Object對象>
知識點:反射機制調用對象的無參構造實例化對象.
2.5 DI依賴注入
依賴注入,即組件之間的依賴關系由容器在應用系統運行期來決定,也就是由容器動態地將某種依賴關系的目標對象實例注入到應用系統中的各個關聯的組件之中。
簡單來說,所謂的依賴注入其實就是,在創建對象的同時或之后,如何給對象的屬性賦值。
set方式注入:
1、創建User類,聲明name和age屬性,並添加對應的setter和getter方法,以及toString方法
2、在applicationContext.xml中聲明User類的bean實例
3、修改applicationContext.xml中User實例的聲明,為User實例注入屬性(或者在applicationContext.xml中,將UserInfo對象作為值,賦值給User對象的userInfo屬性)
構造方法注入:
1、為User類聲明構造函數
2、修改applicationContext.xml文件,將set方式修改為構造方法注入。
2.6 底層原理(常見面試題)
1、什么是 Spring 框架?Spring 框架有哪些主要模塊?
Spring框架是一個為 Java 應用程序的開發提供了綜合、廣泛的基礎性支持的 Java 平台。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注於應用程序的開發。Spring 框架本身亦是按照設計模式精心打造,這使得我們可以在開發環境中安心的集成 Spring框架,不必擔心Spring 是如何在后台進行工作的。
Spring 框架至今已集成了 20 多個模塊。這些模塊主要被分如下圖所示的核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。
3、使用 Spring 框架能帶來哪些好處?
下面列舉了一些使用 Spring 框架帶來的主要好處:
1、Dependency Injection(DI) 方法使得構造器和 JavaBean properties 文件中的依賴關系一目了然。
2、與 EJB 容器相比較,IOC 容器更加趨向於輕量級。這樣一來 IOC 容器在有限的內存和 CPU資源的情況下進行應用程序的開發和發布就變得十分有利。
3、Spring 並沒有閉門造車,Spring 利用了已有的技術比如 ORM 框架、logging 框架、J2EE、
Quartz 和 JDK Timer,以及其他視圖技術。
4、Spring 框架是按照模塊的形式來組織的。由包和類的編號就可以看出其所屬的模塊,開發者僅僅需要選用他們需要的模塊即可。
5、要測試一項用 Spring 開發的應用程序十分簡單,因為測試相關的環境代碼都已經囊括在框架中了。更加簡單的是,利用 JavaBean 形式的 POJO 類,可以很方便的利用依賴注入來寫入測試數據。
6、Spring 的 Web 框架亦是一個精心設計的 Web MVC 框架,為開發者們在 web 框架的選擇上提供了一個除了主流框架比如 Struts、過度設計的、不流行 web 框架的以外的有力選項。
7、Spring 提供了一個便捷的事務管理接口,適用於小型的本地事務處理(比如在單 DB 的環境下)和復雜的共同事務處理(比如利用 JTA 的復雜 DB 環境)。
4、請解釋下 Spring 框架中的 IOC?
Spring 中的 org.springframework.beans 包和 org.springframework.context 包構成了
Spring 框架 IOC 容器的基礎。BeanFactory 接口提供了一個先進的配置機制,使得任何類型的對象的配置成為可能。
ApplicationContex 接口對 BeanFactory(是一個子接口)進行了擴展,在 BeanFactory 的基礎上添加了其他功能,比如與 Spring 的 AOP 更容易集成,也提供了處理 message resource的機制(用於國際化)、事件傳播以及應用層的特別配置,比如針對 Web 應用的
WebApplicationContext。
5、BeanFactory 和 ApplicationContext 有什么區別?
BeanFactory 可以理解為含有 bean 集合的工廠類。BeanFactory 包含了種 bean 的定義,以便在接收到客戶端請求時將對應的 bean 實例化。BeanFactory 還能在實例化對象時生成協作類之間的關系。此舉將 bean 自身與 bean 客戶端的配置中解放出來。BeanFactory 還包含了 bean 生命周期的控制,調用客戶端的初始化方法(initialization methods)和銷毀方法(destruction methods)。從表面上看,application context 如同 bean factory 一樣具有 bean 定義、bean 關聯關系的設置,根據請求分發 bean 的功能。但 application context 在此基礎上還提供了其他的功能。
1.提供了支持國際化的文本消息
2.統一的資源文件讀取方式
3.已在監聽器中注冊的 bean 的事件
以下是三種較常見的 ApplicationContext 實現方式:
1、ClassPathXmlApplicationContext:從 classpath 的 XML 配置文件中讀取上下文,並生成上下文定義。應用程序上下文從程序環境變量中取得。
ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);
2、FileSystemXmlApplicationContext :由文件系統中的 XML 配置文件讀取上下文。
ApplicationContext context = new FileSystemXmlApplicationContext(“application.xml”);
3、XmlWebApplicationContext:由 Web 應用的 XML 文件讀取上下文。
6、Spring 提供幾種配置方式來設置元數據?
將 Spring 配置到應用開發中有以下三種方式:
1.基於 XML 的配置
2.基於注解的配置
3.基於 Java 的配置
7、如何使用 XML 配置的方式配置 Spring?
在 Spring 框架中,依賴和服務需要在專門的配置文件來實現,常用 XML 格式的配置文件。這些配置文件的格式通常用開頭,然后一系列的 bean 定義和專門的應用配置選項組成。SpringXML配置的主要目的時候是使所有的Spring組件都可以用xml文件的形式來進行配置。這意味着不會出現其他的 Spring 配置類型(比如聲明的方式或基於 Java Class 的配置方式)Spring 的 XML 配置方式是使用被 Spring 命名空間的所支持的一系列的 XML 標簽來實現的。
Spring 有以下主要的命名空間:context、beans、jdbc、tx、aop、mvc 和 aso。
8、如何用基於 Java 配置的方式配置 Spring?
Spring 對 Java 配置的支持是由@Configuration 注解和@Bean 注解來實現的。由@Bean注解的方法將會實例化、配置和初始化一個新對象,這個對象將由 Spring 的 IOC 容器來管理。@Bean 聲明所起到的作用與 元素類似。被@Configuration 所注解的類則表示這個類的主要目的是作為 bean 定義的資源。被@Configuration 聲明的類可以通過在同一個類的內部調用@bean 方法來設置嵌入 bean 的依賴關系。
9、怎樣用注解的方式配置 Spring?
Spring 在 2.5 版本以后開始支持用注解的方式來配置依賴注入。可以用注解的方式來替代 XML方式的 bean 描述,可以將 bean 描述轉移到組件類的內部,只需要在相關類上、方法上或者字段聲明上使用注解即可。注解注入將會被容器在 XML 注入之前被處理,所以后者會覆蓋掉前者對於同一個屬性的處理結果。
注解裝配在 Spring 中是默認關閉的。所以需要在 Spring 文件中配置一下才能使用基於注解的裝配模式。如果你想要在你的應用程序中使用關於注解的方法的話,請參考如下的配置。
context:annotation-config/
10、請解釋 Spring Bean 的生命周期?
Spring Bean 的生命周期簡單易懂。在一個 bean 實例被初始化時,需要執行一系列的初始化操作以達到可用的狀態。同樣的,當一個 bean 不在被調用時需要進行相關的析構操作,並從 bean容器中移除。Spring bean factory 負責管理在 spring 容器中被創建的 bean 的生命周期。Bean 的生命周期由兩組回調(call back)方法組成。
1.初始化之后調用的回調方法。
2.銷毀之前調用的回調方法。
Spring 框架提供了以下四種方式來管理 bean 的生命周期事件:
1、InitializingBean 和 DisposableBean 回調接口
2、針對特殊行為的其他 Aware 接口
3、Bean 配置文件中的 Custom init()方法和 destroy()方法
4、@PostConstruct 和@PreDestroy 注解方式
使用 customInit()和 customDestroy()方法管理 bean 生命周期的代碼樣例如下:
11、Spring Bean 作用域之間的區別?
Spring 容器中的 bean 可以分為 5 個范圍。所有范圍的名稱都是自說明的,但是為了避免混淆,
還是讓我們來解釋一下:
1.singleton:這種 bean 范圍是默認的,這種范圍確保不管接受到多少個請求,每個容器中只有一個 bean 的實例,單例的模式由 bean factory 自身來維護。
2.prototype:原形范圍與單例范圍相反,為每一個 bean 請求提供一個實例。
3.request:在請求 bean 范圍內會每一個來自客戶端的網絡請求創建一個實例,在請求完成以后,bean 會失效並被垃圾回收器回收。
4.Session:與請求范圍類似,確保每個 session 中有一個 bean 的實例,在 session 過期后,bean 會隨之失效。
5.global-session:global-session 和 Portlet 應用相關。當你的應用部署在 Portlet 容器中工作時,它包含很多 portlet。如果你想要聲明讓所有的 portlet 共用全局的存儲變量的話,那么這全局變量需要存儲在 global-session 中。全局作用域與 Servlet 中的 session 作用域效果相同。
12、什么是 Spring inner beans?
在 Spring 框架中,無論何時 bean 被使用時,當僅被調用了一個屬性。一個明智的做法是將這個 bean 聲明為內部 bean。內部 bean 可以用 setter 注入“屬性”和構造方法注入“構造參數”的方式來實現。比如,在我們的應用程序中,一個 Customer 類引用了一個 Person 類,我們的要做的是創建一個 Person 的實例,然后在 Customer 內部使用。
public class Customer{
private Person person;
}
public class Person{
private String name;
private String address;
private int age;
//Setters and Getters
}
內部 bean 的聲明方式如下:
13、Spring 框架中的單例 Beans 是線程安全的么?
Spring 框架並沒有對單例 bean 進行任何多線程的封裝處理。關於單例 bean 的線程安全和並發問題需要開發者自行去搞定。但實際上,大部分的 Spring bean 並沒有可變的狀態(比如Serview類和DAO類),所以在某種程度上說Spring的單例bean是線程安全的。如果你的bean有多種狀態的話(比如 View Model 對象),就需要自行保證線程安全。
最淺顯的解決辦法就是將多態 bean 的作用域由“singleton”變更為“prototype”。
14、請舉例說明如何在 Spring 中注入一個 Java 集合?
Spring 提供了以下四種集合類的配置元素:
1、該標簽用來裝配可重復的 list 值。
2、該標簽用來裝配沒有重復的 set 值。
3、該標簽可用來注入鍵和值可以為任何類型的鍵值對。
4、該標簽支持注入鍵和值都是字符串類型的鍵值對。
下面看一下具體的例子:
15、如何向 Spring Bean 中注入 java.util.Properties?
第一種方法是使用如下面代碼所示的 標簽:
也可用”util:”命名空間來從 properties 文件中創建出一個 propertiesbean,然后利用 setter方法注入 bean 的引用。
16、請解釋 Spring Bean 的自動裝配?
在 Spring 框架中,在配置文件中設定 bean 的依賴關系是一個很好的機制,Spring 容器還可以自動裝配合作關系 bean 之間的關聯關系。這意味着 Spring 可以通過向 Bean Factory 中注入的方式自動搞定 bean 之間的依賴關系。自動裝配可以設置在每個 bean 上,也可以設定在特定的 bean 上。
下面的 XML 配置文件表明了如何根據名稱將一個 bean 設置為自動裝配:
除了 bean 配置文件中提供的自動裝配模式,還可以使用@Autowired 注解來自動裝配指定的bean。在使用@Autowired 注解之前需要在按照如下的配置方式在 Spring 配置文件進行配置才可以使用。
<context:annotation-config />
也可以通過在配置文件中配置 AutowiredAnnotationBeanPostProcessor 達到相同的效果。
配置好以后就可以使用@Autowired 來標注了。
@Autowired
public EmployeeDAOImpl ( EmployeeManager manager ) {
this.manager = manager;
}
17、請解釋各種自動裝配模式的區別?
在 Spring 框架中共有 5 種自動裝配,讓我們逐一分析。
1.no:這是 Spring 框架的默認設置,在該設置下自動裝配是關閉的,開發者需要自行在 bean定義中用標簽明確的設置依賴關系。
2.byName:該選項可以根據 bean 名稱設置依賴關系。當向一個 bean 中自動裝配一個屬性時,容器將根據 bean 的名稱自動在在配置文件中查詢一個匹配的 bean。如果找到的話,就裝配這個屬性,如果沒找到的話就報錯。
3.byType:該選項可以根據 bean 類型設置依賴關系。當向一個 bean 中自動裝配一個屬性時,容器將根據 bean 的類型自動在在配置文件中查詢一個匹配的 bean。如果找到的話,就裝配這個屬性,如果沒找到的話就報錯。
4.constructor:造器的自動裝配和 byType 模式類似,但是僅僅適用於與有構造器相同參數的bean,如果在容器中沒有找到與構造器參數類型一致的 bean,那么將會拋出異常。
5.autodetect:該模式自動探測使用構造器自動裝配或者 byType 自動裝配。首先,首先會嘗試
找合適的帶參數的構造器,如果找到的話就是用構造器自動裝配,如果在 bean 內部沒有找到相
應的構造器或者是無參構造器,容器就會自動選擇 byTpe 的自動裝配方式。
18、如何開啟基於注解的自動裝配?
要使用 @Autowired,需要注冊 AutowiredAnnotationBeanPostProcessor,可以有以下兩
種方式來實現:
1、引入配置文件中的下引入
<context:annotation-config />
2、在 bean 配置文件中直接引入 AutowiredAnnotationBeanPostProcessor
19 、自動裝配有哪些局限性?
自動裝配有如下局限性:
重寫:你仍然需要使用 和< property>設置指明依賴,這意味着總要重寫自動裝配。
原生數據類型:你不能自動裝配簡單的屬性,如原生類型、字符串和類。
模糊特性:自動裝配總是沒有自定義裝配精確,因此,如果可能盡量使用自定義裝配。
20、在 Spring 中可以注入 null 或空字符串嗎?
完全可以。
21、請舉例解釋@Required Annotation?
在產品級別的應用中,IOC 容器可能聲明了數十萬了 bean,bean 與 bean 之間有着復雜的依賴關系。設值注解方法的短板之一就是驗證所有的屬性是否被注解是一項十分困難的操作。可以通過在中設置“dependency-check”來解決這個問題。在應用程序的生命周期中,你可能不大願意花時間在驗證所有 bean 的屬性是否按照上下文文件正 確 配 置 。 或 者 你 寧 可 驗 證 某 個 bean 的 特 定 屬 性 是 否 被 正 確 的 設 置 。 即 使 是 用“dependency-check”屬性也不能很好的解決這個問題,在這種情況下,你需要使用@Required 注解。
需要用如下的方式使用來標明 bean 的設值方法。
public class EmployeeFactoryBean extends AbstractFactoryBean