SSM基礎重難點


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標簽之外,還有哪些標簽?
答: ,加上動態sql的9個標簽,其中 為sql片段標簽,通過 標簽引入sql片段, 為不支持自增的主鍵生成策略標簽。

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/

在標簽配置完成以后,就可以用注解的方式在 Spring 中向屬性、方法和構造方法中自動裝配變量。 下面是幾種比較重要的注解類型: 1.@Required:該注解應用於設值方法。 2.@Autowired:該注解應用於有值設值方法、非設值方法、構造方法和變量。 3.@Qualifier:該注解和@Autowired 注解搭配使用,用於消除特定 bean 自動裝配的歧義。 4.JSR-250 Annotations :Spring 支持 基於 JSR-250 注解 的以下 注解 ,@Resource、 @PostConstruct 和 @PreDestroy。

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、該標簽支持注入鍵和值都是字符串類型的鍵值對。
下面看一下具體的例子:

INDIA Pakistan USA UK INDIA Pakistan USA UK admin@gupaoedu.com support@gupaoedu.com

15、如何向 Spring Bean 中注入 java.util.Properties?
第一種方法是使用如下面代碼所示的 標簽:

admin@gupaoedu.com support@gupaoedu.com

也可用”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{
private String designation;
public String getDesignation() {
return designation;
}
@Required
public void setDesignation(String designation) {
this.designation = designation;
}
}
RequiredAnnotationBeanPostProcessor 是 Spring 中的后置處理用來驗證被@Required 注解的 bean 屬性是否被正確的設置了。在使用 RequiredAnnotationBeanPostProcesso 來驗證bean 屬性之前,首先要在 IOC 容器中對其進行注冊:

但 是 如 果 沒 有 屬 性 被 用 @Required 注 解 過 的 話 , 后 置 處 理 器 會 拋 出 一 個BeanInitializationException 異常。

22、請舉例解釋@Autowired 注解?
@Autowired 注解對自動裝配何時何處被實現提供了更多細粒度的控制。@Autowired 注解可
以像@Required 注解、構造器一樣被用於在 bean 的設值方法上自動裝配 bean 的屬性,一個參數或者帶有任意名稱或帶有多個參數的方法。
比如,可以在設值方法上使用@Autowired 注解來替代配置文件中的 元素。當 Spring 容器在setter 方法上找到@Autowired 注解時,會嘗試用 byType 自動裝配。
當然我們也可以在構造方法上使用@Autowired 注解。帶有@Autowired 注解的構造方法意味
着在創建一個 bean 時將會被自動裝配,即便在配置文件中使用 元素。
public class TextEditor {
private SpellChecker spellChecker;
@Autowired
public TextEditor(SpellChecker spellChecker){
System.out.println("Inside TextEditor constructor." );
this.spellChecker = spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
下面是沒有構造參數的配置方式:

context:annotation-config/

23、請舉例說明@Qualifier 注解?
@Qualifier 注解意味着可以在被標注 bean 的字段上可以自動裝配。Qualifier 注解可以用來取消 Spring 不能取消的 bean 應用。
下面的示例將會在 Customer 的 person 屬性中自動裝配 person 的值。
public class Customer{
@Autowired
private Person person;
}
下面我們要在配置文件中來配置 Person 類。







Spring 會知道要自動裝配哪個 person bean 么?不會的,但是運行上面的示例時,會拋出下面的異常:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.gupaoedu.common.Person] is defined:
expected single matching bean but found 2: [personA, personB]
要解決上面的問題,需要使用 @Quanlifier 注解來告訴 Spring 容器要裝配哪個 bean:
public class Customer{
@Autowired
@Qualifier("personA")
private Person person;
}

24、構造方法注入和設值注入有什么區別?
請注意以下明顯的區別:
1.在設值注入方法支持大部分的依賴注入,如果我們僅需要注入 int、string 和 long 型的變量,我們不要用設值的方法注入。對於基本類型,如果我們沒有注入的話,可以為基本類型設置默認值。在構造方法注入不支持大部分的依賴注入,因為在調用構造方法中必須傳入正確的構造參數,否則的話為報錯。
2.設值注入不會重寫構造方法的值。如果我們對同一個變量同時使用了構造方法注入又使用了設
置方法注入的話,那么構造方法將不能覆蓋由設值方法注入的值。很明顯,因為構造方法盡在對
象被創建時調用。
3.在使用設值注入時有可能還不能保證某種依賴是否已經被注入,也就是說這時對象的依賴關系
有可能是不完整的。而在另一種情況下,構造器注入則不允許生成依賴關系不完整的對象。
4. 在 設 值 注 入 時 如 果 對 象 A 和 對 象 B 互 相 依 賴 , 在 創 建 對 象 A 時 Spring 會 拋 出
sObjectCurrentlyInCreationException 異常,因為在 B 對象被創建之前 A 對象是不能被創建
的,反之亦然。所以 Spring 用設值注入的方法解決了循環依賴的問題,因對象的設值方法是在
對象被創建之前被調用的。更多面試資料在群619881427免費獲取(JVM/並發編程/分布式/微服務/等面試疑難解答都可以群里免費獲取)

25、Spring 框架中有哪些不同類型的事件?
Spring 的 ApplicationContext 提供了支持事件和代碼中監聽器的功能。
我們可以創建 bean 用來監聽在 ApplicationContext 中發布的事件。ApplicationEvent 類和
在 ApplicationContext 接口中處理的事件,如果一個 bean 實現了 ApplicationListener 接口,
當一個 ApplicationEvent 被發布以后,bean 會自動被通知。

public class AllApplicationEventListener implements ApplicationListener <
ApplicationEvent > {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent)
{
//process event
}
}
Spring 提供了以下5種標准的事件:
1.上下文更新事件(ContextRefreshedEvent):該事件會在 ApplicationContext 被初始化或
者更新時發布。也可以在調用 ConfigurableApplicationContext 接口中的 refresh()方法時被
觸發。
2.上下文開始事件(ContextStartedEvent):當容器調用 ConfigurableApplicationContext
的 Start()方法開始/重新開始容器時觸發該事件。
3.上下文停止事件(ContextStoppedEvent):當容器調用 ConfigurableApplicationContext
的 Stop()方法停止容器時觸發該事件。
4.上下文關閉事件(ContextClosedEvent):當 ApplicationContext 被關閉時觸發該事件。
容器被關閉時,其管理的所有單例 Bean 都被銷毀。
5.請求處理事件(RequestHandledEvent):在 Web 應用中,當一個 http 請求(request)
結束觸發該事件。
除了上面介紹的事件以外,還可以通過擴展 ApplicationEvent 類來開發自定義的事件。
public class CustomApplicationEvent extends ApplicationEvent{
public CustomApplicationEvent ( Object source, final String msg ){
super(source);
System.out.println("Created a Custom event");
}
}

為了監聽這個事件,還需要創建一個監聽器:
public class CustomEventListener implements ApplicationListener <
CustomApplicationEvent >{
@Override
public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
//handle event
}
}
之后通過 applicationContext 接口的 publishEvent()方法來發布自定義事件。
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext,
“Test message”);
applicationContext.publishEvent(customEvent);

26、FileSystemResource 和 ClassPathResource 有何區別?
在 FileSystemResource 中需要給出 spring-config.xml 文件在你項目中的相對路徑或者絕對
路徑。在 ClassPathResource 中 spring 會在 ClassPath 中自動搜尋配置文件,所以要把
ClassPathResource 文件放在 ClassPath 下。
如果將 spring-config.xml 保存在了 src 文件夾下的話,只需給出配置文件的名稱即可,因為 src
文件夾是默認。
簡而言之,ClassPathResource 在環境變量中讀取配置文件,FileSystemResource 在配置文件
中讀取配置文件。

27、Spring 框架中都用到了哪些設計模式?
Spring 框架中使用到了大量的設計模式,下面列舉了比較有代表性的:
1、代理模式—在 AOP 和 remoting 中被用的比較多。
2、單例模式:在 spring 配置文件中定義的 bean 默認為單例模式。
3、模板模式:用來解決代碼重復的問題。
比如. RestTemplate, JmsTemplate, JpaTemplate。
4、委派模式:Spring 提供了 DispatcherServlet 來對請求進行分發。
5、工廠模式:BeanFactory 用來創建對象的實例,貫穿於 BeanFactory / ApplicationContext
接口的核心理念。
6、代理模式:AOP 思想的底層實現技術,Spring 中采用 JDK Proxy 和 CgLib 類庫。

28、在 Spring 框架中如何更有效的使用 JDBC?
使用Spring JDBC框架,資源管理以及錯誤處理的代價都會減輕。開發人員只需通過statements
和 queries 語句從數據庫中存取數據。Spring 框架中通過使用模板類能更有效的使用 JDBC,
也就是所謂的 JdbcTemplate。

29、Spring5 新特性
1、依賴 JDK 8+和 Java EE7+以上版本
2、首次采用反應式編程模型
3、支持使用注解進行編程
4、新增函數式編程
5、支持使用 REST 斷點執行反應式編程
6、支持 HTTP 2.0
7、新增 Kotlin 和 Spring WebFlux
8、可使用 Lambda 表達式注冊 Bean
9、Spring WebMVC 支持最新的 API
10、使用 JUnit5 執行條件和並發測試
11、使用 Spring WebFlux 執行集成測試
12、核心容器優化

2.7 Spring事務管理
事務就是對一系列的數據庫操作(比如插入多條數據)進行統一的提交或回滾操作,如果插入成功,那么一起成功,如果中間有一條出現異常,那么回滾之前的所有操作。這樣可以防止出現臟數據,防止數據庫數據出現問題。
開發中為了避免這種情況一般都會進行事務管理。Spring中也有自己的事務管理機制,一般是使用TransactionMananger進行管 理,可以通過Spring的注入來完成此功能。
Spring支持如下兩種方式的事務管理:
編程式事務管理:這意味着你可以通過編程的方式管理事務,這種方式帶來了很大的靈活性,但很難維護。
聲明式事務管理:這種方式意味着你可以將事務管理和業務代碼分離。你只需要通過注解或者XML配置管理事務。
一般選擇聲明式事務管理,因為這種方式和應用程序的關聯較少
(事務的注解為@Transactional)

2.8 AOP
2.8.1 概念
AOP 是軟件設計領域中的面向切面編程,它是面向對象編程(OOP)的一種補充和完善實際項目中我們通常將面向對象理解為一個靜態過程(例如一個系統有多少模塊,一個模塊有哪些對象,對象有哪些屬性),面向切面中包含一個一個動態過程(在對象運行時動態織入一些功能。)
AOP就是要在基於OCP(開閉原則)在不改變原有系統核心業務代碼的基礎上動態添加一些擴展功能並可以控制對象的執行(例如添加日志、權限控制等)。
什么是AOP? 面向切面編程(AOP)完善spring的依賴注入(DI),面向切面編程在spring中主要表現為兩個方面
1.面向切面編程提供聲明式事務管理
2.spring支持用戶自定義的切面 面向切面編程(aop)是對面向對象編程(oop)的補充, 面向對象編程將程序分解成各個層次的對象,面向切面編程將程序運行過程分解成各個切面。 AOP從程序運行角度考慮程序的結構,提取業務處理過程的切面,oop是靜態的抽象,aop是動態的抽象, 是對應用執行過程中的步驟進行抽象,,從而獲得步驟之間的邏輯划分。

aop框架具有的兩個特征:
1.各個步驟之間的良好隔離性
2.源代碼無關性
前提:要實現AOP的模擬就要知道動態代理,Spring中使用了兩種動態代理方式,一種是基於JDK的動態代理,一種是基於CGlib的動態代理。為什么會有兩種,那是因為JDK的動態代理只能是針對接口。

2.8.2 實現AOP
@Aspect 注解用於標識此類為一個AOP橫切面對象
@Pointcut 注解用於定義本類中的切入點,本案例中切入點表達式用的是bean表達式,這個表達式以bean開頭,bean括號中的內容為一個spring管理的某個bean對象的id。
@Around用於定義一個環繞通知(滿足切入點表達式的核心業務方法執行之前和之后執行的一個操作)

在AOP編程中有五種類型的通知:
1)前置通知 (@Before) 方法執行之前執行
2)返回通知 (@AfterReturning) 方法return之后執行
3)異常通知 (@AfterThrowing) 方法出現異常之后執行
4)后置通知 (@After) : 又稱之為最終通知(finally)
5)環繞通知 (@Around) :重點掌握(優先級最高)

AOP總結:
1.AOP中環繞通知使用是最多.因為可以控制目標方法是否執行.
2.除了環繞通知,另外四大通知類型 只做記錄.不做修改.

2.9 單例模式和多例模式
什么是單例多例:
所謂單例就是所有的請求都用一個對象來處理,比如我們常用的service和dao層的對象通常都是單例的,而多例則指每個請求用一個新的對象來處理,比如action;

如何產生單例多例:
在通用的SSH中,單例在spring中是默認的,如果要產生多例,則在配置文件的bean中添加scope=“prototype”;

為什么用單例多例:
之所以用單例,是因為沒必要每個請求都新建一個對象,這樣子既浪費CPU又浪費內存;
之所以用多例,是為了防止並發問題;即一個請求改變了對象的狀態,此時對象又處理另一個請求,而之前請求對對象狀態的改變導致了對象對另一個請求做了錯誤的處理;
用單例和多例的標准只有一個:
當對象含有可改變的狀態時(更精確的說就是在實際應用中該狀態會改變),則多例,否則單例;

何時用單例?何時用多例?
對於struts2來說,action必須用多例,因為action本身含有請求參數的值,即可改變的狀態;
而對於STRUTS1來說,action則可用單例,因為請求參數的值是放在actionForm中,而非action中的;
另外要說一下,並不是說service或dao一定是單例,標准同第3點所講的,就曾見過有的service中也包含了可改變的狀態,同時執行方法也依賴該狀態,但一樣用的單例,這樣就會出現隱藏的BUG,而並發的BUG通常很難重現和查找;

3、SpringMVC
3.1 概念
Springmvc是spring框架的一個模塊,spring和springmvc無需中間整合層整合,
Springmvc是一個基於mvc的web框架
3.2 MVC設計模式
MVC設計模式是一種通用的軟件編程思想
在MVC設計模式中認為, 任何軟件都可以分為三部分組成:
(1)控制程序流轉的控制器(Controller)
(2)封裝數據處理數據的模型(Model)
(3)負責展示數據的視圖(view)
並且在MVC設計思想中要求一個符合MVC設計思想的軟件應該保證上面這三部分相互獨立,互不干擾,每一個部分只負責自己擅長的部分。
如果某一個模塊發生變化,應該盡量做到不影響其他兩個模塊。這樣做的好處是,軟件的結構會變得更加的清晰,可讀性強。有利於后期的擴展和維護,並且代碼可以實現復用。

3.3 SpringMVC執行原理

(1).用戶發送請求 至 前端控制器(DispatcherServlet);
提示:DispatcherServlet的作用:接收請求,調用其它組件處理請求,響應結果,相當於轉發器、中央處理器,是整個流程控制的中心
(2).前端控制器(DispatcherServlet)收到請求后調用處理器映射器(HandlerMapping)
處理器映射器(HandlerMapping)找到具體的Controller(可以根據xml配置、注解進行查找),並將Controller返回給DispatcherServlet;
(3).前端控制器(DispatcherServlet)調用處理器適配器(HandlerAdapter)。處理器適配器經過適配調用具體的Controller;(Controller--> service --> Dao --> 數據庫)
Controller執行完成后返回ModelAndView,
提示:Model(模型數據,即Controller處理的結果,Map) View(邏輯視圖名,即負責展示結果的JSP頁面的名字)
處理器適配器(HandlerAdapter)將controller執行的結果(ModelAndView)返回給前端控制器(DispatcherServlet);
(4).前端控制器(DispatcherServlet)將執行的結果(ModelAndView)傳給視圖解析器(ViewReslover)
視圖解析器(ViewReslover)根據View(邏輯視圖名)解析后返回具體JSP頁面
(5).前端控制器(DispatcherServlet)根據Model對View進行渲染(即將模型數據填充至視圖中);
(6).前端控制器(DispatcherServlet)將填充了數據的網頁響應給用戶。

其中整個過程中需要開發人員編寫的部分有 Controller、Service、Dao、View;

常見面試題
1、什么是Spring MVC ?簡單介紹下你對springMVC的理解?
Spring MVC是一個基於Java的實現了MVC設計模式的請求驅動類型的輕量級Web框架,通過把Model,View,Controller分離,將web層進行職責解耦,把復雜的web應用分成邏輯清晰的幾部分,簡化開發,減少出錯,方便組內開發人員之間的配合。

2、SpringMVC的流程?
(1)用戶發送請求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到請求后,調用HandlerMapping處理器映射器,請求獲取Handle;
(3)處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一並返回給DispatcherServlet;
(4)DispatcherServlet 調用 HandlerAdapter處理器適配器;
(5)HandlerAdapter 經過適配調用 具體處理器(Handler,也叫后端控制器);
(6)Handler執行完成返回ModelAndView;
(7)HandlerAdapter將Handler執行結果ModelAndView返回給DispatcherServlet;
(8)DispatcherServlet將ModelAndView傳給ViewResolver視圖解析器進行解析;
(9)ViewResolver解析后返回具體View;
(10)DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)
(11)DispatcherServlet響應用戶。

3、Springmvc的優點:
(1)可以支持各種視圖技術,而不僅僅局限於JSP;
(2)與Spring框架集成(如IoC容器、AOP等);
(3)清晰的角色分配:前端控制器(dispatcherServlet) , 請求到處理器映射(handlerMapping), 處理器適配器(HandlerAdapter), 視圖解析器(ViewResolver)。
(4)支持各種請求資源的映射策略。

4、Spring MVC的主要組件?
(1)前端控制器 DispatcherServlet(不需要程序員開發)
作用:接收請求、響應結果,相當於轉發器,有了DispatcherServlet 就減少了其它組件之間的耦合度。
(2)處理器映射器HandlerMapping(不需要程序員開發)
作用:根據請求的URL來查找Handler
(3)處理器適配器HandlerAdapter
注意:在編寫Handler的時候要按照HandlerAdapter要求的規則去編寫,這樣適配器HandlerAdapter才可以正確的去執行Handler。
(4)處理器Handler(需要程序員開發)
(5)視圖解析器 ViewResolver(不需要程序員開發)
作用:進行視圖的解析,根據視圖邏輯名解析成真正的視圖(view)
(6)視圖View(需要程序員開發jsp)
View是一個接口, 它的實現類支持不同的視圖類型(jsp,freemarker,pdf等等)

5、springMVC和struts2的區別有哪些?
(1)springmvc的入口是一個servlet即前端控制器(DispatchServlet),而struts2入口是一個filter過慮器(StrutsPrepareAndExecuteFilter)。
(2)springmvc是基於方法開發(一個url對應一個方法),請求參數傳遞到方法的形參,可以設計為單例或多例(建議單例),struts2是基於類開發,傳遞參數是通過類的屬性,只能設計為多例。
(3)Struts采用值棧存儲請求和響應的數據,通過OGNL存取數據,springmvc通過參數解析器是將request請求內容解析,並給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最后又將ModelAndView中的模型數據通過reques域傳輸到頁面。Jsp視圖解析器默認使用jstl。

6、SpringMVC怎么樣設定重定向和轉發的?
(1)轉發:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"

7、SpringMvc怎么和AJAX相互調用的?
通過Jackson框架就可以把Java里面的對象直接轉化成Js可以識別的Json對象。具體步驟如下 :(springmvc底層會將結果封裝成json格式返回)
(1)加入Jackson.jar
(2)在配置文件中配置json的映射
(3) 在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。

8、如何解決POST請求中文亂碼問題,GET的又如何處理呢?
(1)解決post請求亂碼問題:
在web.xml中配置一個CharacterEncodingFilter過濾器,設置成utf-8;
(2)get請求中文參數出現亂碼解決方法有兩個:
①修改tomcat配置文件添加編碼與工程編碼一致,如下:
<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
②另外一種方法對參數進行重新編碼:
String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默認編碼,需要將tomcat編碼后的內容按utf-8編碼。

9、Spring MVC的異常處理?
答:可以將異常拋給Spring框架,由Spring框架來處理;我們只需要配置簡單的異常處理器,在異常處理器中添視圖頁面即可。

10、SpringMvc的控制器是不是單例模式,如果是,有什么問題,怎么解決?
答:是單例模式,所以在多線程訪問的時候有線程安全問題,不要用同步,會影響性能的,解決方案是在控制器里面不能寫字段。

11、 SpringMVC常用的注解有哪些?
@RequestMapping:用於處理請求 url 映射的注解,可用於類或方法上。用於類上,則表示類中的所有響應請求的方法都是以該地址作為父路徑。
@RequestBody:注解實現接收http請求的json數據,將json轉換為java對象。
@ResponseBody:注解實現將conreoller方法返回對象轉化為json對象響應給客戶。

12、SpingMvc中的控制器的注解一般用那個,有沒有別的注解可以替代?
答:一般用@Conntroller注解,表示是表現層,不能用別的注解代替。

13、如果在攔截請求中,我想攔截get方式提交的方法,怎么配置?
答:可以在@RequestMapping注解里面加上method=RequestMethod.GET。

14、怎樣在方法里面得到Request,或者Session?
答:直接在方法的形參中聲明request,SpringMvc就自動把request對象傳入。

15、如果想在攔截的方法里面得到從前台傳入的參數,怎么得到?
答:直接在形參里面聲明這個參數就可以,但必須名字和傳過來的參數一樣。

16、如果前台有很多個參數傳入,並且這些參數都是一個對象的,那么怎么樣快速得到這個對象?
答:直接在方法中聲明這個對象,SpringMvc就自動會把屬性賦值到這個對象里面。

17、SpringMvc中函數的返回值是什么?
答:返回值可以有很多類型,有String, ModelAndView。ModelAndView類把視圖和數據都合並的一起的,但一般用String比較好。

18、SpringMvc用什么對象從后台向前台傳遞數據的?
答:通過ModelMap對象,可以在這個對象里面調用put方法,把對象加到里面,前台就可以通過el表達式拿到。

19、怎么樣把ModelMap里面的數據放入Session里面?
答:可以在類上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。

20、SpringMvc里面攔截器是怎么寫的:
有兩種寫法,一種是實現HandlerInterceptor接口,另外一種是繼承適配器類,接着在接口方法當中,實現處理邏輯;然后在SpringMvc的配置文件中配置攔截器即可:

mvc:interceptors



mvc:interceptor
<mvc:mapping path="/modelMap.do" />

</mvc:interceptor>
</mvc:interceptors>

21、注解原理:
注解本質是一個繼承了Annotation的特殊接口,其具體實現類是Java運行時生成的動態代理類。我們通過反射獲取注解時,返回的是Java運行時生成的動態代理對象。通過代理對象調用自定義注解的方法,會最終調用AnnotationInvocationHandler的invoke方法。該方法會從memberValues這個Map中索引出對應的值。而memberValues的來源是Java常量池。

SSM常見面試題

1、SpringMVC與Struts2的主要區別?
①springmvc的入口是一個servlet即前端控制器,而struts2入口是一個filter過慮器。
②springmvc是基於方法開發,傳遞參數是通過方法形參,可以設計為單例或多例(建議單例),struts2是基於類開發,傳遞參數是通過類的屬性,只能設計為多例。 
③Struts采用值棧存儲請求和響應的數據,通過OGNL存取數據, springmvc通過參數解析器是將request對象內容進行解析成方法形參,將響應數據和頁面封裝成ModelAndView對象,最后又將模型數據通過request對象傳輸到頁面。 Jsp視圖解析器默認使用jstl。

2、Spring中用到哪些設計模式?
1.工廠模式(BeanFactory中)
2.單例模式(Spring中默認bean為單例)
3.適配器模式(HandlerAdater)
4.裝飾者模式
5.代理模式(AOP中用到JDK動態代理)
6.觀察者模式(listener的實現,例如ApplicationListener)
7.策略模式(定義一系列的算法,把它們一個個的封裝起來,並且使它們可以相互替換。在實例化對象時用到)
8.模板模式(jdbcTemplate)

1.SpringMVC的工作流程?

  1. 用戶發送請求至前端控制器DispatcherServlet
  2. DispatcherServlet收到請求調用HandlerMapping處理器映射器。
  3. 處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一並返回給DispatcherServlet。
  4. DispatcherServlet通過HandlerAdapter處理器適配器調用處理器
  5. 執行處理器(Controller,也叫后端控制器)。
  6. Controller執行完成返回ModelAndView
  7. HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet
  8. DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器
  9. ViewReslover解析后返回具體View
  10. DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)。
  11. DispatcherServlet響應用戶

2.Spring在SSM起什么作用?
Spring是一個輕量級框架,也是一個容器,Spring實質上講就是一個Bean工廠,主要用來管理Bean的生命周期和框架集成。有IOC控制反轉,DI依賴注入,控制反轉是把dao依賴注入到servic層,然后service層反轉給action層,Spring的頂層容器為BeanFactory,常用的ApplicationContext為它的子接口,實現了工廠模式,Spring還提供了AOP的支持,方便在切面級開發,

3. 怎么樣理解IOC和DI   
 在使用Spring框架的過程中、一定會用到控制反轉、但是往往所需要的資源還需要其他資源的支持、這個過程就需要依賴注入的支持

4. Spring的事務,事務的作用          
編程式事務管理:這意味你通過編程的方式管理事務,給你帶來極大的靈活性,但是難維護。
聲明式事務管理:這意味着你可以將業務代碼和事務管理分離,你只需用注解和XML配置來管理事務。

5.Spring的IOC你在項目中是怎么使用的?
IOC主要來解決對象之間的依賴問題,把所有的bean的依賴關系通過配置文件或者注解關聯起來,降低了耦合度

6.Spring的配置文件有哪些內容?   
開啟事務注解驅動
事務管理器
開啟注解功能,並配置掃描包
配置數據源
配置SQL會話工廠、別名、映射文件
不用編寫DAO層的實現類(代理模式)

7.說下Spring的注解?    
@Controller
@Service
@Component
@RequestMapping
@Resource、@Autowired
@ResponseBody
@Transactional

8.Spring DI的幾種方式?
(1)構造器注入:通過構造方法初始化
<constructor-arg name=”dao”
(2)setter注入:通過setter方法初始化注入

注意:在實際開發中常用setter注入。

9.@RequestMapping注解用在類上面有什么作用?
該注解是用來映射一個URL到一個類或一個特定的方處理方法上。

10.SpringMVC怎么樣設定重定向和轉發的    
在返回值前面加”forward:”就可以讓結果轉發,譬如”forward:user.do?name=method4” 在返回值前面加”redirect:”就可以讓返回值重定向,譬如”redirect:http://www.uu456.com

11. MyBatis怎么配置一對多?
一對多的關系 :property: 指的是集合屬性的值, ofType:指的是集合中元素的類型

  1. MyBatis怎樣配置多對一?          
    多對一的關系:property: 指的是屬性的值, javaType:指的是屬性的類型

13.簡單介紹下你對mybatis的理解?

  1. mybatis配置
  2. SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息。
  3. mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載。
  4. 通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠
  5. 由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行。
  6. mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。
  7. Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id。
  8. Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。
  9. Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql后將輸出結果映射至java對象中,輸出結果映射過程相當於jdbc編程中對結果的解析處理過程。

14、springmvc是線程安全的嗎
springmvc是單例模式的框架,但它是線程安全的,因為springmvc沒有成員變量,所有參數的封裝都是基於方法的,屬於當前線程的私有變量. 因此是線程安全的框架


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM