1.IOC與DI
-
inverse of control 控制反轉(zhuǎn)
我們創(chuàng)建對象的方式反轉(zhuǎn)了狂男。以前對象的創(chuàng)建由開發(fā)人員自己維護属拾,包括依賴注入也是自己注入舞萄。使用spring之后见转,對象的創(chuàng)建及依賴關(guān)系可以由spring完成創(chuàng)建及依賴注入水醋。
控制反轉(zhuǎn)反轉(zhuǎn)的是對象的創(chuàng)建方式旗笔,由自己創(chuàng)建改為由程序創(chuàng)建
-
dependency injection依賴注入
實現(xiàn)IOC思想需要di支持。
注入方法:set方法注入拄踪,構(gòu)造方法注入蝇恶,字段注入
注入類型:值類型注入(8大基本數(shù)據(jù)類型),引用類型注入
2.BeanFactory與ApplicationContext
-
BeanFactory
spring原始接口惶桐,針對原始接口的實現(xiàn)類的功能比較單一
BeanFactory接口實現(xiàn)類的容器撮弧,特點是每次在獲得對象時才會創(chuàng)建對象
-
ApplicationContext
每次容器啟動時就會創(chuàng)建容器中配置的所有對象
ClassPathXmlApplicationContext:從類路徑下加載配置文件 FileSystemXmlApplicationContext:從磁盤絕對路徑下加載配置文件
-
如果想讓Spring容器隨項目的創(chuàng)建而創(chuàng)建潘懊,隨項目的關(guān)閉而銷毀贿衍,需要在web.xml中監(jiān)聽Application創(chuàng)建銷毀監(jiān)聽器(
ServletContextListener
)的實現(xiàn)類org.springframework.web.context.ContextLoaderListener
并通過<context-param>來指定配置文件位置<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
web開發(fā)中使用ApplicationContext,在資源匱乏的環(huán)境下可以使用BeanFactory
3.配置詳解
-
Bean元素 ---- 描述需要Spring容器管理的對象
-
name
給被管理對象起個名稱释树,獲得對象時,根據(jù)該名成獲得對象擎淤,可以重復,可以使用特殊字符
-
class
被管理對象的完整類名
-
scope
- singleton:單例對象(默認值),標識為單例的對象在spring容器中只會被創(chuàng)建一次
- prototype:多例原型,被標識為多例的對象嘴拢,每次獲得時才會創(chuàng)建,每次創(chuàng)建時都是新的對象炊汤,整合struts2時正驻,ActionBean必須為多例-->
-
init-method
配置一個方法為生命周期的初始方法抢腐,spring會在創(chuàng)建對象后立即調(diào)用
-
destroy-method
配置一個方法為生命周期的銷毀方法,spring容器在關(guān)閉并銷毀所有容器中的對象之前調(diào)用
<bean name="user" class="com.spring.learn1.entity.User" scope="singleton" init-method="init" destroy-method="destory"/>
-
-
導入其他Spring配置文件
<import resource="com/spring/learn1/applicationContext.xml"/>
-
Spring 創(chuàng)建對象的方式
-
空參創(chuàng)建
<bean name="user" class="com.spring.learn1.entity.User"/>
-
靜態(tài)工廠
//調(diào)用UserFactory的createUser方法來創(chuàng)建對象,createUser為靜態(tài)方法 <bean name="user" class="com.spring.learn1.entity.UserFactory" factory-method="createUser"/>
-
實例工廠
//創(chuàng)建UserFactory對象伤靠,調(diào)用UserFactory的createUser方法來創(chuàng)建對象 <bean name="user" factory-bean="userFactory" factory-method="createUser"/> <bean factory-bean="userFactory" class="com.spring.learn1.entity.UserFactory"/>
-
-
Spring屬性注入方式
-
set方法注入
//name:屬性名稱; value:值; ref:對象 <bean name="user" class="com.spring.learn1.entity.User"> <property name="name" value="tom"/> <property name="age" value="18"/> <property name="car" ref="car"/> </bean> <bean name="car" class="com.spring.learn1.entity.Car"> <property name="carName" value="瑪莎拉蒂"/> </bean>
-
構(gòu)造函數(shù)注入
//constructor-arg:構(gòu)造參數(shù) name:參數(shù)名稱 type:參數(shù)類型 index:注入位置 ref:對象 value:值 <bean name="user" class="com.spring.learn1.entity.User"> <constructor-arg name="name" type="java.lang.String" index="0" value="tom"/> <constructor-arg name="age" type="java.lang.Integer" index="1" value="20"/> <constructor-arg name="car" ref="car" index="2"/> </bean>
-
p名稱空間注入
xmlns:p="http://www.springframework.org/schema/p" <bean name="user" class="com.spring.learn1.entity.User" p:name="jack" p:age="16" p:car-ref="car"/> <bean name="car" class="com.spring.learn1.entity.Car"> <property name="carName" value="瑪莎拉蒂"/> </bean>
-
spel(Spring Expression Language,Spring 表達式語言)注入
<bean name="user" class="com.spring.learn1.entity.User"> <constructor-arg name="name" type="java.lang.String" index="0" value="tom"/> <constructor-arg name="age" type="java.lang.Integer" index="1" value="20"/> <constructor-arg name="gender" type="java.lang.String" index="2" value="男"/> <constructor-arg name="car" ref="car" index="3"/> </bean> <bean name="car" class="com.spring.learn1.entity.Car"> <property name="carName" value="瑪莎拉蒂"/> </bean> <bean name="user2" class="com.spring.learn1.entity.User"> <property name="name" value="#{user.name}"/><!-- 引用user的name --> <property name="gender" value="#{'女'}"/><!-- 定義為女 --> <property name="age" value="#{user.getAge()}"/><!-- 通過調(diào)用方法設(shè)置age --> <property name="car" ref="car"/><!-- 引用對象采用此方式 --> </bean>
-
-
Spring復雜類型注入
數(shù)組
list
map
-
properties
<bean name="ot" class="com.spring.learn1.entity.OT"> <!-- 如果數(shù)組中只準備注入一個值或者一個對象宴合,直接使用value或ref即可 --> <!--<property name="sUsers" ref="user"/>--> <property name="sUsers"> <array> <value>"tom"</value> <value>"jerry"</value> <ref bean="user2"/> </array> </property> <!-- 如果list,set中只準備注入一個值或者一個對象迹鹅,直接使用value或ref即可 --> <!--<property name="userList" ref="user"/>--> <property name="userList"> <list> <value>"tom"</value> <value>"jerry"</value> <ref bean="user2"/> </list> </property> <!-- Map注入 --> <property name="userMap"> <map> <entry key="name" value="tom"/> <entry key="age" value="14"/> <entry key="lover" value-ref="user2"/> <entry key-ref="user2" value-ref="user"/> </map> </property> <property name="userProperties"> <props> <prop key="user" >root</prop> <prop key="password">123</prop> </props> </property> </bean>
4.Spring生命周期管理
-
web.xml配置
添加監(jiān)聽器
org.springframework.web.context.ContextLoaderListener
-
指定配置文件位置
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
-
獲取
WebApplicationContextUtils.getWebApplicationContext(ServletContext)
5.AOP
-
底層實現(xiàn)原理(采用以下兩種混合式開發(fā)斜棚,有接口優(yōu)先采用動態(tài)代理)
-
動態(tài)代理(實現(xiàn)InvocationHandler接口)
被代理對象必須要實現(xiàn)接口才能產(chǎn)生代理對象
public class UserFactory implements InvocationHandler { UserService userService; public UserFactory(UserService userService) { this.userService = userService; } public UserService getUserServiceProxy(){ return (UserService) Proxy.newProxyInstance(UserFactory.class.getClassLoader(),UserServiceImpl.class.getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開啟事務"); method.invoke(userService,args); System.out.println("關(guān)閉事務"); return null; } }
-
cglib代理(第三方代理技術(shù)弟蚀,實現(xiàn)MethodInterceptor接口)
可以對任何類生成代理,原理是對目標對象進行繼承代理昧绣,如果目標對象被final修飾夜畴,則該類無法對該對象代理
public class MyCglbProxy implements MethodInterceptor { public UserServiceImpl getProxy() { Enhancer enhancer = new Enhancer();//幫我們生成代理對象 enhancer.setSuperclass(UserServiceImpl.class);//設(shè)置代理的目標 enhancer.setCallback(this);//代理的操作 return (UserServiceImpl) enhancer.create();//創(chuàng)建代理對象 } @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("開啟事務"); methodProxy.invokeSuper(object, args); System.out.println("關(guān)閉事務"); return null; } }
-
-
AOP相關(guān)術(shù)語
- Joinpoint(連接點):目標對象中可以進行增強的方法,即可以被攔截到的點贪绘。在 spring 中,這些點指的是方法,因為 spring 只支持方法類型的連接點.
- Pointcut(切入點):目標對象中已經(jīng)增強的方法兔簇,所謂切入點是指我們要對哪些 Joinpoint 進行攔截增強.
- Advice(通知/增強):需要增強的代碼硬耍,所謂通知是指攔截到 Joinpoint 之后所要做的事情就是通知.通知分為前置通知,后置通知,異常通知,最終通知,環(huán)繞通知(切面要完成的功能)
- Introduction(引介):引介是一種特殊的通知在不修改類代碼的前提下, Introduction 可以在運行期為類
動態(tài)地添加一些方法或Field. - Target(目標對象):代理的目標對象
- Weaving(織入):是指把Advice應用到Target來創(chuàng)建新的代理對象的過程.spring 采用動態(tài)代理織入经柴,而 AspectJ 采用編譯期織入和類裝載期織入
- Proxy(代理) :一個類被 AOP 織入增強后,就產(chǎn)生一個結(jié)果代理類
- Aspect(切面): 是切入點和通知(引介)的結(jié)合
-
AOP開發(fā)步驟
定義目標對象
-
定義增強類
public class MyAdvice { // 前置通知 public void before() { System.out.println("這是前置通知"); } // 后置通知(如果出現(xiàn)異常不會通知) public void after() { System.out.println("這是后置通知,如果出現(xiàn)異常不會調(diào)用"); } // 異常通知 public void afterException() { System.out.println("這是異常通知"); } // 最終通知(無論是否出現(xiàn)異常翻擒,都會進行通知) public void end() { System.out.println("這是最終通知,無論是否出現(xiàn)異常陋气,都會進行通知"); } // 環(huán)繞通知(通知之前之后都會調(diào)用,切面要完成的功能) public Object around(ProceedingJoinPoint point) throws Throwable { System.out.println("這是環(huán)繞通知,之前的部分"); Object proceed = point.proceed();//調(diào)用目標方法 System.out.println("這是環(huán)繞通知,之后的部分"); return proceed; } }
-
將通知織入目標對象
導入aop約束命名空間
aop
-
配置目標對象
<!--配置目標對象--> <bean class="com.spring.learn3.entity.UserServiceImpl" name="target"/>
-
配置通知對象
<!--配置通知對象--> <bean class="com.spring.learn3.entity.MyAdvice" name="advice"/>
-
將通知織入目標對象
<!--織入--> <aop:config> <!--配置切入點--> <aop:pointcut id="user" expression="execution(* com.spring.learn3.entity.*ServiceImpl.*(..))" <aop:aspect ref="advice"> <!--前置通知(1)--> <aop:before method="before" pointcut-ref="user"/> <!--最終通知(2)--> <aop:after method="end" pointcut-ref="user"/> <!--環(huán)繞通知(3)--> <aop:around method="around" pointcut-ref="user"/> <!--后置通知(4)--> <aop:after-returning method="after" pointcut-ref="user"/> <!--異常通知(5)--> <aop:after-throwing method="afterException" pointcut-ref="user"/> </aop:aspect> </aop:config> //正常調(diào)用順序1-3-4-3-2 //異常調(diào)用順序1-3-5-2
?
6)Spring整合JDBC----JdbcTemplate
-
JdbcTemplate使用方法
//準備連接池 ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://39.106.1.213:3306/hb?characterEncoding=utf-8"); dataSource.setUser("root"); dataSource.setPassword("123456"); //建立JDBC模板對象 JdbcTemplate template = new JdbcTemplate(dataSource); //執(zhí)行sql語句 String sql = "insert into User values(null,'肉絲')"; template.update(sql);
-
Spring整合JDBC
-
Dao實現(xiàn)類中添加JdbcTemplate屬性,實現(xiàn)set方法,依賴關(guān)系Dao---->JdbcTemplate---->DataSource
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://39.106.1.213:3306/hb? characterEncoding=utf-8"/> <property name="user" value="xxx"/> <property name="password" value="xxx"/> </bean> <bean name="template" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean name="userDao" class="com.dao.test1.entity.UserDaoImpl"> <property name="template" ref="template"/> </bean>
Dao繼承JdbcDaoSupport類议慰,該類設(shè)置連接池時自動創(chuàng)建JdbcTemplate,依賴關(guān)系Dao---->DataSource
-
-
讀取外部Properties
-
建立properties文件
//src目錄下db.properties jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql://39.106.1.213:3306/hb?characterEncoding=utf-8 jdbc.user=root jdbc.password=123456
-
配置
<!--指定Spring讀取db.properties--> <context:property-placeholder location="classpath:db.properties"/> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean>
-
7)Spring事務
-
平臺事務管理器
PlatformTransactionManager() ---- DataSourceTransactionManager(使用JDBC或iBatis進行持久化數(shù)據(jù)時使用) ---- HibernateTransactionManager(使用Hibernate進行持久化數(shù)據(jù)時使用)
-
事務定義信息TransactionDefinition
事務的隔離級別
是否只讀
-
事務的傳播行為(決定業(yè)務方法之間調(diào)用别凹,事務應該如何處理)
保證同一個事務中
PROPAGATION_REQUIRED 支持當前事務洽糟,如果不存在,就新建一個(默認)
PROPAGATION_SUPPORTS 支持當前事務颁督,如果不存在沉御,就不使用事務
PROPAGATION_MANDATORY 支持當前事務昭灵,如果不存在伐谈,拋出異常-
保證沒有在同一個事務中
PROPAGATION_REQUIRES_NEW 如果有事務存在诵棵,掛起當前事務祝旷,創(chuàng)建一個新的事務
PROPAGATION_NOT_SUPPORTED 以非事務方式運行,如果有事務存在距贷,掛起當前事務
PROPAGATION_NEVER 以非事務方式運行吻谋,如果有事務存在漓拾,拋出異常
PROPAGATION_NESTED 如果當前事務存在,則嵌套事務執(zhí)行
超時信息
事務的狀態(tài) TransactionStatus
-
Spring管理事務方式
-
編碼式 ---- 使用模板(TransactionTemplate)執(zhí)行事務
-
調(diào)用模板執(zhí)行事務
private TransactionTemplate transactionTemplate; transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { //數(shù)據(jù)庫業(yè)務 } });
-
Spring中進行配置
-
將核心事務管理器配置到spring
<context:property-placeholder location="classpath:db.properties"/> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 事務核心管理器,封裝了所有事務操作低千,依賴連接池--> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
-
配置TransactionTemplate模板
<!--事務模板對象--> <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean>
-
配置操作事務的類栋操,將事務模板注入
<bean name="" class=""> <property name="transactionTemplate" ref="transactionTemplate"/> </bean>
-
-
-
xml配置(AOP)
-
導入約束
beans: 最基本
context:讀取properties配置
aop:配置aop
tx:配置事務通知 -
配置通知(以方法為參數(shù)進行配置)
<context:property-placeholder location="classpath:db.properties"/> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 事務核心管理器矾芙,封裝了所有事務操作,依賴連接池--> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置事務通知 --> <tx:advice transaction-manager="transactionManager"> <!-- name:方法名稱 isolation="DEFAULT" 隔離級別 propagation="REQUIRED" 傳播行為 read-only="false" 只讀 timeout="-1" 過期時間 rollback-for="" -Exception no-rollback-for="" +Exception --> <tx:attributes> <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/> <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/> <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/> <tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/> <tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/> <tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/> <tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/> <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/> </tx:attributes> </tx:advice>
-
織入
<!-- 配置織入--> <aop:config> <!-- 配置切點表達式--> <aop:pointcut id="txPc" expression="execution(* com.dao.test2.AccountServiceImpl.transfer())"/> <!-- 配置切面:通知+切點--> <!-- advice-ref:通知名稱--> <!-- pointcut-ref:切點名稱--> <aop:advisor advice-ref="txadvice" pointcut-ref="txPc"/> </aop:config>
-
-
注解配置(AOP)
導入約束
-
配置xml
<context:property-placeholder location="classpath:db.properties"/> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 事務核心管理器,封裝了所有事務操作感帅,依賴連接池--> <bean name="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transaction"/>
-
類或方法添加注解
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly = false)
?
-