對Spring的理解
spring是一個輕量級的開源框架,貫穿持久層、業務邏輯層、控制層。讓每個功能模塊均可以獨立的分開,下降耦合度,提升代碼複用度。spring經過控制反轉下降耦合性,一個對象的依賴經過被動的注入而非主動的new。spring還包括面向切面、MVC整合等等。以上是我對spring的淺顯認識。html
Spring IOC的理解
控制反轉,指由Spring來控制對象的生命週期和對象間的關係。之前對象的建立時機是由本身把握的,開發人員主動建立對象,如今由IOC容器建立,而後注入。全部的類都會在IOC容器中註冊,告訴spring你是什麼,你須要什麼,spring容器在合適的時機將你所須要的東西給你,控制對象生命週期的再也不是引用它的對象而是spring容器。前端
spring先加載xml文件,Bean先在spring容器中註冊,而後會進行初始化Bean,再將Bean存到容器的緩存區(Map),誰須要就給它注入,並且緩存區的對象還在,一直在,這屬於單例,直到關閉spring。(scope見下面)java
DI:依賴注入,動態的向某個對象注入它所須要的對象。spring
SpringAOP(攔截器的實現原理)
http://www.cnblogs.com/xiaolovewei/p/7919763.htmlsql
Spring事務
http://www.cnblogs.com/xiaolovewei/p/9418874.html數據庫
Spring 中的scope ,也就是Bean的做用域
scope有Singleton、Prototype、request、session、global session。其中主要的是singleton和prototype。編程
singleton指的是IOC容器中只存在一個實例,全部對該對象的引用都要共享該實例。該對象自從第一次被建立之後,直到容器退出纔會被銷燬。就像上面說的,容器中有一個緩存區(MAP)保管這個單例。設計模式
prototype:IOC容器接收到對該對象的請求時,就會新建一個對象實例給對方。返回給對方之後,IOC容器就不在持有該對象的引用,也就是IOC只負責建立該對象實例,置於銷燬,就無論了。緩存
request:XmlWebApplicationContext會爲每一個HTTP請求建立一個對象,當請求結束,該對象也就被銷燬。安全
session:會爲每一個session建立一個對象,存活時間爲session
Spring常見建立對象的註解?
@Component@Controller@ Service@ Repository <context:compenent-scan base-package="">
xml:<bean>無參構造器、靜態工廠(get方法)。
對象(屬性)注入的方式
xml:set方法(<property name value>)、構造器(<constructor-arg name value>)
註解:Autowired、Resource
Spring中用到的設計模式
答:簡單工廠、工廠方法、單例模式、適配器、包裝器、代理、觀察者、策略、模板方法
Spring的優勢?
答:1.下降了組件之間的耦合性 ,實現了軟件各層之間的解耦
2.可使用容易提供的衆多服務,如事務管理,消息服務等
3.容器提供單例模式支持
4.容器提供了AOP技術,利用它很容易實現如權限攔截,運行期監控等功能
5.容器提供了衆多的輔助類,能加快應用的開發
6.spring對於主流的應用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring屬於低侵入式設計,代碼的污染極低
8.獨立於各類應用服務器
9.spring的DI機制下降了業務對象替換的複雜性
10.Spring的高度開放性,並不強制應用徹底依賴於Spring,開發者能夠自由選擇spring 的部分或所有
Spring 的自動裝配
https://www.cnblogs.com/xiaolovewei/p/9424804.html
byName/byType/constructor
咱們在xml中注入對象,使用<property>屬於手動裝配,自動裝配不須要寫這個。如byName,類中對象的屬性名與bean的名字同樣(id)則直接注入。
Autowired和Resource
https://www.cnblogs.com/xiaolovewei/p/9424856.html
Autowired默認使用byType,單例沒問題,Spring的註解。若是想使用byName,則和Qualifier("")一塊兒使用。
Resource(name="")默認byName。J2EE的註解
Spring保證安全性
首先,Controller、Dao、service都是單例的,就有可能出現多線程的安全問題----有類成員變量,這樣多線程訪問就會使用到共享變量了。
避免:不要使用類成員變量,這樣就不會有共享變量了。或者使用ThreadLocal
使用多例,scope="property"。這樣每一個線程都有本身的對象,就不會出現問題。
SpringMVC理解
spring MVC 其實就是 spring 本身作了一套很合適的 controller層 框架。結合性更好。 這個東西的核心就是 Dispatcher(能夠理解成一個servlet),根據配置映射的JSP文件路徑進行跳轉。controller層也可使用annotation(註解)的方式來描述。MVC的中的C。
SpringMVC流程(原理)
1 用戶發送請求至前端控制器DispatcherServlet;
2 前端控制器調用處理器映射器HandlerMapping,處理器映射器根據URL找到具體的處理器(Handler,也就是Controller),並返回給前端控制器。
3 前端控制器經過處理器適配器HandlerAdapter調用處理器。
4 執行處理器(Controller),執行完後返回給前端控制器一個ModelAndView
5 前端控制器調用視圖解析器ViewResolver解析視圖,並返回View給前端控制器。
6 前端控制器渲染並顯示視圖。
SpringMVC優勢
1. 能夠任意使用各類視圖技術,而不只僅侷限於JSP
2. 支持各類請求資源的映射策略
3 .它應是易於擴展的
SpringMVC對請求的攔截方式
<servlet-mapping> 中的<url-pattern>/<url-pattern>。/表明攔截全部請求,包括靜態資源。 .action攔截對應action結尾的路徑,不會攔截靜態資源。
對於/,解決靜態資源不被攔截的方法:<mvc:resource location="/WEB-INF/js/" mapping="/js/**"> 全部對mapping的訪問,都轉到location位置。
<mvc:annotation-driven>
springmvc須要配置HandlerMapping、HandlerAdapter、ViewResolver。而<mvc:annotation-driven>會自動配置RequestMappingHandlerMapping和RequestMaappingHandlerAdapter。
MyBatis
MyBatis是一個優秀的持久層框架,它對jdbc的操做數據庫的過程進行封裝,使開發者只須要關注 SQL 自己,而不須要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。
Mybatis經過xml或註解的方式將要執行的各類statement(statement、preparedStatemnt、CallableStatement)配置起來,並經過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。
Mybatis解決jdbc編程的問題
一、 數據庫連接建立、釋放頻繁形成系統資源浪費從而影響系統性能,若是使用數據庫連接池可解決此問題。
解決:在SqlMapConfig.xml中配置數據連接池,使用鏈接池管理數據庫連接。
二、 Sql語句寫在代碼中形成代碼不易維護,實際應用sql變化的可能較大,sql變更須要改變java代碼。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。
三、 向sql語句傳參數麻煩,由於sql語句的where條件不必定,可能多也可能少,佔位符須要和參數一一對應。
解決:Mybatis自動將java對象映射至sql語句,經過statement中的parameterType定義輸入參數的類型。
四、 對結果集解析麻煩,sql變化致使解析代碼變化,且解析前須要遍歷,若是能將數據庫記錄封裝成pojo對象解析比較方便。
解決:Mybatis自動將sql執行結果映射至java對象,經過statement中的resultType定義輸出結果的類型。
Mapper接口開發的一些規範
1.mapper.xml中的namespace和mapper接口類路徑相同;
2.mapper.xml中的SQL對應的id與mapper接口的方法名相同;
3.mapper.xml中的每一個sql的parameterType和接口的輸入參數類型相同;
4.mapper.xml中的每一個sql的resultType要與接口的返回參數類型相同
#{name}獲取parameterType中的屬性的值,若輸入對象,name就是對應的字段,輸入hashmap,name就是key。
resultType總結:
resultType中對象的字段名和查詢出來的結果的字段名相同。
返回單個pojo對象要保證sql查詢出來的結果集爲單條,內部使用sqlsession.selectOne方法調用,mapper接口使用pojo對象做爲方法返回值。
返回pojo列表表示查詢出來的結果集可能爲多條,內部使用sqlsession.selectList方法,mapper接口使用List<pojo>對象做爲方法返回值。
resultMap
若是sql查詢字段名和對象的屬性名不一致,能夠經過resultMap將字段名和屬性名做一個對應關係 ,resultMap實質上還須要將查詢結果映射到pojo對象中。
resultMap處理關聯查詢返回的結果
一對一:類中除了基本的屬性,還包含其餘對象,orders中含有User,使用association標籤
<resultMap type="cn.itcast.mybatis.po.Orders" id="userordermap">
<!-- 這裏的id,是mybatis在進行一對一查詢時將user字段映射爲user對象時要使用,必須寫 -->
<id property="id" column="id"/>
<result property="user_id" column="user_id"/>
<result property="number" column="number"/>
<association property="user" javaType="cn.itcast.mybatis.po.User">
<!-- 這裏的id爲user的id,若是寫上表示給user的id屬性賦值 -->
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
</association>
</resultMap>
一對多:類中除了基本的屬性外,還包含對象的集合,orders中含有List<Orderdetail>。使用collection標籤
<resultMap type="cn.itcast.mybatis.po.Orders" id="userorderdetailmap">
<id property="id"column="id"/>
<result property="user_id" column="user_id"/>
<result property="number" column="number"/>
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<id property="id" column="orderdetail_id"/>
<result property="items_id" column="items_id"/>
<result property="items_num" column="items_num"/>
</collection>
</resultMap>
多對多:User中包含List<Orders>,Orders中包含List<Orderdetail>。collection中嵌套collection。
MyBatis延遲加載
查詢關聯信息時(須要關聯對象,要查關聯表),首次查詢只查詢主要信息(單表查詢),關聯信息等用戶獲取時再查詢(須要查詢關聯表),大大緩解了數據庫壓力。association和collection都具有延遲加載的功能。
這個跟 本身在作項目時同樣,先查詢單表,若是還須要其餘表關聯信息,再查詢其餘表。
sqlmapconfig.xml中
<settings>
<!--開啓延遲加載-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--關閉積極加載-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--查詢訂單和建立訂單的用戶,使用延遲加載-->
<resultMap id="OrderAndUserLazyLoad" type="Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId" />
<result column="number" property="number" />
<result column="createtime" property="createtime" />
<result column="note" property="note" />
<!--
select:要延遲加載的statement的id colunm:關聯兩張表的那個列的列名 -->
<association property="user" javaType="User" select="findUser" column="user_id">
<--select中就是延遲加載再去執行的sql-->
</association>
</resultMap>
<select id="findOrdersByLazyLoad" resultMap="OrderAndUserLazyLoad"> SELECT * FROM orders </select>
<select id="findUser" parameterType="int" resultType="User"> SELECT * FROM User WHERE id = #{value} </select>
從上面看,其實就是單表查詢兩次。
Mybatis緩存
Mybatis一級緩存的做用域是同一個SqlSession,在同一個sqlSession中兩次執行相同的sql語句,第一次執行完畢會將數據庫中查詢的數據寫到緩存(內存),第二次會從緩存中獲取數據將再也不從數據庫查詢,從而提升查詢效率。當一個sqlSession結束後該sqlSession中的一級緩存也就不存在了。當遇到增刪改時會清空緩存。Mybatis默認開啓一級緩存。
Mybatis二級緩存是多個SqlSession共享的,其做用域是mapper的同一個namespace,不一樣的sqlSession兩次執行相同namespace下的sql語句且向sql中傳遞參數也相同即最終執行相同的sql語句,第一次執行完畢會將數據庫中查詢的數據寫到緩存(內存),第二次會從緩存中獲取數據將再也不從數據庫查詢,從而提升查詢效率。當遇到增刪改時會清空緩存。Mybatis默認沒有開啓二級緩存須要在setting全局參數中配置開啓二級緩存。
#{}和${}的區別
#{}是預編譯處理,${}是字符串替換。 Mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值; Mybatis在處理${}時,就是把${}替換成變量的值。 使用#{}能夠有效的防止SQL注入,提升系統安全性。
當實體類中的屬性名和表中的字段名不同 ,怎麼辦 ?
1。查詢語句中,給字段名取別名。
2.。resultMap
模糊查詢like語句該怎麼寫?
1.在Java代碼中寫。string wildcardname = 「%smi%」; list<name> names = mapper.selectlike(wildcardname);
2.Java代碼中傳入變量,SQL語句中拼接通配符,會引發SQL注入。select * from foo where bar like "%"${value}"%"
mapper如何傳遞多個參數
1.包裝成pojo對象。
2.map
Mybatis的Xml映射文件中,不一樣的Xml映射文件,id是否能夠重複?
不一樣的Xml映射文件,若是配置了namespace,那麼id能夠重複;若是沒有配置namespace,那麼id不能重複;畢竟namespace不是必須的,只是最佳實踐而已。
一般一個Xml映射文件,都會寫一個Dao接口與之對應,請問,這個Dao接口的工做原理是什麼?Dao接口裏的方法,參數不一樣時,方法能重載嗎?
Dao接口,就是人們常說的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內的參數,就是傳遞給sql的參數。Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串做爲key值,可惟必定位一個MappedStatement,舉例:com.mybatis3.mappers.StudentDao.findStudentById,能夠惟一找到namespace爲com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每個<select>、<insert>、<update>、<delete>標籤,都會被解析爲一個MappedStatement對象。
Dao接口裏的方法,是不能重載的,由於是全限名+方法名的保存和尋找策略。
Dao接口的工做原理是JDK動態代理,Mybatis運行時會使用JDK動態代理爲Dao接口生成代理proxy對象,代理對象proxy會攔截接口方法,轉而執行MappedStatement所表明的sql,而後將sql執行結果返回。