您好,登錄后才能下訂單哦!
這篇文章主要介紹了Spring框架怎么用,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Spring框架是由于軟件開發(fā)的復(fù)雜性而創(chuàng)建的。Spring使用的是基本的JavaBean來(lái)完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限于服務(wù)器端的開發(fā)。從簡(jiǎn)單性、可測(cè)試性和松耦合性角度而言,絕大部分Java應(yīng)用都可以從Spring中受益。Spring是一個(gè)輕量級(jí)控制反轉(zhuǎn)(IoC)和面向切面(AOP)的容器框架。
◆目的:解決企業(yè)應(yīng)用開發(fā)的復(fù)雜性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企業(yè)應(yīng)用功能
◆范圍:任何Java應(yīng)用
控制反轉(zhuǎn)(Inversion of Control,英文縮寫為IoC)把創(chuàng)建對(duì)象的權(quán)利交給框架,是框架的重要特征,并非面向?qū)ο缶幊痰膶S眯g(shù)語(yǔ)。它包括依賴注入和依賴查找。傳統(tǒng)的業(yè)務(wù)層,當(dāng)需要資源時(shí)就在該業(yè)務(wù)層new資源,這樣耦合性(程序之間相互依賴關(guān)聯(lián))較高?,F(xiàn)在將new的部分交給spring,做到高內(nèi)聚低耦合。簡(jiǎn)而言之:原先是每當(dāng)調(diào)用dao層或service層方法時(shí),由app來(lái)new,現(xiàn)在是將new的權(quán)利交給spring,要什么資源從spring中獲??!
1.下載框架所需的依賴jar包
spring官網(wǎng)為:http://spring.io/
下載jar包: http://repo.springsource.org/libs-release-local/org/springframework/spring
2.導(dǎo)入基本jar包
其實(shí)基本核心jar有beans;context;core;expression包,其他是依賴log4j日志。當(dāng)然spring的jar不止這些,后期慢慢加上。
3.配置log4j配置文件
日志文件定義在src目錄下
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=info, stdout
4.測(cè)試日志文件是否部署成功
package com.clj.demo1; import org.apache.log4j.Logger; import org.junit.Test; /** * 演示日志用法 * @author Administrator * */ public class Demo1 { //創(chuàng)建日志類 private Logger log=Logger.getLogger(Demo1.class); @Test public void run1(){ //可以將log4j.rootLogger屬性中的info改為off則不會(huì)再控制臺(tái)顯示 log.info("執(zhí)行了"); } }
5.定義一個(gè)接口和實(shí)現(xiàn)類
接口:
package com.clj.demo2; public interface UserService { public void sayHello(); }
實(shí)現(xiàn)類
package com.clj.demo2; public class UserServiceImpl implements UserService{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void init(){ System.out.println("初始化。。"); } public void sayHello() { System.out.println("Hello Spring"+"\t"+name); } public void destory(){ System.out.println("銷毀。。"); } }
6.定義spring專屬的配置文件
定義名為applicationContext.xml,位置為src下,與日志文件同目錄,導(dǎo)入相對(duì)應(yīng)的約束,并將實(shí)現(xiàn)類注入到配置文件中,剛開始入門,使用bean約束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 使用bean標(biāo)簽 1.id值唯一(必寫) 2.注意:class為實(shí)現(xiàn)類路徑,不是接口(必寫) 3.init-method核心方法執(zhí)行之前初始化工作(選寫) 4.destroy-method核心方法執(zhí)行之后初始化工作(選寫)--> <bean id="userService" class="com.clj.demo2.UserServiceImpl" init-method="init" destroy-method="destory"> <property name="name" value="佳先森"></property> </bean> </beans>
7.測(cè)試
public class Demo1 { /** * 原始方式 */ @Test public void run(){ //創(chuàng)建實(shí)現(xiàn)類 UserServiceImpl s=new UserServiceImpl(); s.setName("佳先森"); s.sayHello(); } /** * 老的工廠版本BeanFactory * 舊的工廠不會(huì)創(chuàng)建配置文件對(duì)象 */ @Test public void run2(){ BeanFactory factory=new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); UserService us=(UserService)factory.getBean("userService"); us.sayHello(); } /** * 使用spring框架IOC方式 * 新版本factory創(chuàng)建啟動(dòng)服務(wù)器會(huì)創(chuàng)建配置文件對(duì)象,再次調(diào)用時(shí)無(wú)需加載工廠 */ @Test public void run3(){ //創(chuàng)建工廠,加載核心配置文件(ClassPathXmlApplicationContext從src下找) ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); //從工廠中獲取到對(duì)象(配置文件中的id值,這里用了多態(tài)) UserService usi=(UserService) ac.getBean("userService"); //調(diào)用對(duì)象的方法執(zhí)行 usi.sayHello(); } /** * 演示destroy-method方法 * bean摧毀方法不會(huì)自動(dòng)執(zhí)行 * 除非scope= singleton或者web容器中會(huì)自動(dòng)調(diào)用,但是main函數(shù)或測(cè)試用例需要手動(dòng)調(diào)用(需要使用ClassPathXmlApplicationContext的close()方法) */ @Test public void run4(){ //創(chuàng)建工廠,加載核心配置文件(ClassPathXmlApplicationContext從src下找) ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); //從工廠中獲取到對(duì)象(配置文件中的id值,這里用了多態(tài)) UserService usi=(UserService) ac.getBean("userService"); //調(diào)用對(duì)象的方法執(zhí)行 usi.sayHello(); //ApplicationContext實(shí)現(xiàn)類提供close方法,將工廠關(guān)閉就可執(zhí)行destory-method方法 ac.close(); } }
其中舊工廠與新工廠的區(qū)別
* BeanFactory和ApplicationContext的區(qū)別
* BeanFactory -- BeanFactory采取延遲加載,第一次getBean時(shí)才會(huì)初始化Bean
* ApplicationContext -- 在加載applicationContext.xml時(shí)候就會(huì)創(chuàng)建具體的Bean對(duì)象的實(shí)例,還提供了一些其他的功能
* 事件傳遞
* Bean自動(dòng)裝配
* 各種不同應(yīng)用層的Context實(shí)現(xiàn)
總結(jié):這是個(gè)最基本的demo,是將實(shí)現(xiàn)類配置到了spring配置文件中,每次啟動(dòng)服務(wù)器時(shí),就會(huì)加載配置文件,從而實(shí)例化了實(shí)現(xiàn)類
1、什么是依賴注入?
Spring 能有效地組織J2EE應(yīng)用各層的對(duì)象。不管是控制層的Action對(duì)象,還是業(yè)務(wù)層的Service對(duì)象,還是持久層的DAO對(duì)象,都可在Spring的 管理下有機(jī)地協(xié)調(diào)、運(yùn)行。Spring將各層的對(duì)象以松耦合的方式組織在一起,Action對(duì)象無(wú)須關(guān)心Service對(duì)象的具體實(shí)現(xiàn),Service對(duì) 象無(wú)須關(guān)心持久層對(duì)象的具體實(shí)現(xiàn),各層對(duì)象的調(diào)用完全面向接口。當(dāng)系統(tǒng)需要重構(gòu)時(shí),代碼的改寫量將大大減少。依賴注入讓bean與bean之間以配置文件組織在一起,而不是以硬編碼的方式耦合在一起。理解依賴注入
依賴注入(Dependency Injection)和控制反轉(zhuǎn)(Inversion of Control)是同一個(gè)概念。具體含義是:當(dāng)某個(gè)角色(可能是一個(gè)Java實(shí)例,調(diào)用者)需要另一個(gè)角色(另一個(gè)Java實(shí)例,被調(diào)用者)的協(xié)助時(shí),在 傳統(tǒng)的程序設(shè)計(jì)過(guò)程中,通常由調(diào)用者來(lái)創(chuàng)建被調(diào)用者的實(shí)例。但在Spring里,創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來(lái)完成,因此稱為控制反轉(zhuǎn);創(chuàng)建被調(diào)用者 實(shí)例的工作通常由Spring容器來(lái)完成,然后注入調(diào)用者,因此也稱為依賴注入。
不管是依賴注入,還是控制反轉(zhuǎn),都說(shuō)明Spring采用動(dòng)態(tài)、靈活的方式來(lái)管理各種對(duì)象。對(duì)象與對(duì)象之間的具體實(shí)現(xiàn)互相透明?! ?/p>
2. IOC和DI的概念
* IOC -- Inverse of Control,控制反轉(zhuǎn),將對(duì)象的創(chuàng)建權(quán)反轉(zhuǎn)給Spring?。?/p>
* DI -- Dependency Injection,依賴注入,在Spring框架負(fù)責(zé)創(chuàng)建Bean對(duì)象時(shí),動(dòng)態(tài)的將依賴對(duì)象注入到Bean組件中??!
3.演示
對(duì)于類成員變量,常用的注入方式有兩種
屬性set方法注入和構(gòu)造方法注入
先演示第一種:屬性set方法注入
1)持久層
package com.clj.demo3; public class CustomerDaoImpl { public void save(){ System.out.println("我是持久層的Dao"); } }
2)業(yè)務(wù)層
注意:此時(shí)是想將持久層注入到業(yè)務(wù)層,將創(chuàng)建持久層實(shí)例權(quán)利交給框架,條件是業(yè)務(wù)層必須提供持久層的成員屬性和set方法
package com.clj.demo3; /** * 依賴注入之將dao 層注入到service層 * @author Administrator * */ public class CustomerServiceImpl{ //提供成員屬相,提供set方法 private CustomerDaoImpl customerDao; public void setCustomerDao(CustomerDaoImpl customerDao) { this.customerDao = customerDao; } public void save(){ System.out.println("我是業(yè)務(wù)層的service..."); //1.原始方式 //new CustomerDaoImpl().save(); //2.spring 之IOC方式 customerDao.save(); } }
3)配置文件配置
<!-- 演示依賴注入 --> <bean id="customerDao" class="com.clj.demo3.CustomerDaoImpl"/> <bean id="customerService" class="com.clj.demo3.CustomerServiceImpl"> <!-- 將Dao注入到service層 --> <property name="customerDao" ref="customerDao"></property> </bean>
4)測(cè)試
/** * spring 依賴注入方式 * 將dao層注入到service層 */ @Test public void run2(){ //創(chuàng)建工廠,加載配置文件,customerService被創(chuàng)建,從而也創(chuàng)建了customerDao ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); CustomerServiceImpl csi=(CustomerServiceImpl) context.getBean("customerService"); csi.save(); }
第二種:構(gòu)造方法注入
1)pojo類并提供構(gòu)造方法
package com.clj.demo4; /** * 演示的構(gòu)造方法的注入方式 * @author Administrator * */ public class Car1 { private String cname; private Double price; public Car1(String cname, Double price) { super(); this.cname = cname; this.price = price; } @Override public String toString() { return "Car1 [cname=" + cname + ", price=" + price + "]"; } }
2)配置文件配置
<!-- 演示構(gòu)造方法注入方式 --> <bean id="car1" class="com.clj.demo4.Car1"> <!-- 寫法一<constructor-arg name="cname" value="寶馬"/> <constructor-arg name="price" value="400000"/> --> <!--寫法二 --> <constructor-arg index="0" value="寶馬"/> <constructor-arg index="1" value="400000"/> </bean>
3)測(cè)試
@Test public void run1(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); Car1 car=(Car1) ac.getBean("car1"); System.out.println(car); }
拓展:構(gòu)造方法之將一個(gè)對(duì)象注入到另一個(gè)對(duì)象中
1)pojo類:目的:將上列中的車注入到人類,使之成為其中一個(gè)屬性,則必須在此類中提供車的成員屬性,并提供有參構(gòu)造方法
package com.clj.demo4; public class Person { private String name; private Car1 car1; public Person(String name, Car1 car1) { super(); this.name = name; this.car1 = car1; } @Override public String toString() { return "Person [name=" + name + ", car1=" + car1 + "]"; } }
2)配置文件
<!-- 構(gòu)造方法之將一個(gè)對(duì)象注入到另一個(gè)對(duì)象--> <bean id="person" class="com.clj.demo4.Person"> <constructor-arg name="name" value="佳先森"/> <constructor-arg name="car1" ref="car1"/> </bean>
4.如何注入集合數(shù)組
1)定義pojo類
package com.clj.demo4; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; /** * 演示集合注入的方式 * @author Administrator * */ public class User { private String[] arrs; private List<String> list; private Set<String> sets; private Map<String,String> map; private Properties pro; public void setPro(Properties pro) { this.pro = pro; } public void setSets(Set<String> sets) { this.sets = sets; } public void setMap(Map<String, String> map) { this.map = map; } public void setList(List<String> list) { this.list = list; } public void setArrs(String[] arrs) { this.arrs = arrs; } @Override public String toString() { return "User [arrs=" + Arrays.toString(arrs) + ", list=" + list + ", sets=" + sets + ", map=" + map + ", pro=" + pro + "]"; } }
2)配置文件
<!-- 注入集合 --> <bean id="user" class="com.clj.demo4.User"> <!-- 數(shù)組 --> <property name="arrs"> <list> <value>數(shù)字1</value> <value>數(shù)字2</value> <value>數(shù)字3</value> </list> </property> <!-- list集合 --> <property name="list"> <list> <value>金在中</value> <value>王杰</value> </list> </property> <!-- set集合 --> <property name="sets"> <set> <value>哈哈</value> <value>呵呵</value> </set> </property> <!-- map集合 --> <property name="map"> <map> <entry key="aa" value="rainbow"/> <entry key="bb" value="hellowvenus"/> </map> </property> <!-- 屬性文件 --> <property name="pro"> <props> <prop key="username">root</prop> <prop key="password">123</prop> </props> </property> </bean>
3)測(cè)試
/** * 測(cè)試注入集合 */ @Test public void run3(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); User user= (User) ac.getBean("user"); System.out.println(user); }
5.怎么分模塊開發(fā)
在主配置文件加入<import>標(biāo)簽(假如此時(shí)在com.clj.test包下定義了一個(gè)配置文件applicationContext2.xml)
<!-- 分模塊開發(fā)之引入其他配置文件 --> <import resource="com/clj/test/applicationContext2.xml"/>
1、入門
1).導(dǎo)入jar包
除了先前6個(gè)包,玩注解還需一個(gè)spring-aop包
2).持久層和實(shí)現(xiàn)層(這里忽略接口)
持久層
package com.clj.demo1; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; /** * UserDaoImpl交給IOC的容器管理 * @author Administrator * */ public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("保存客戶。。"); } }
業(yè)務(wù)層
package com.clj.demo1; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; public class UserServiceImpl implements UserService{ @Override public void sayHello() { System.out.println("Hello spring"); } }
3).定義配置文件
此時(shí)約束條件需添加context約束,并添加組件掃描
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 開啟注解掃面 :base-package指定掃面對(duì) 包--> <context:component-scan base-package="com.clj.demo1"/> </beans>
4)在實(shí)現(xiàn)類中添加注解
/** * 組件注解,可以用來(lái)標(biāo)記當(dāng)前的類 * 類似<bean id="userService" class="com.clj.demo1.UserServiceImpl"> * value表示給該類起個(gè)別名 */ @Component(value="userService") public class UserServiceImpl implements UserService{ //省略 }
5)編寫測(cè)試
/** * 注解方式 */ @Test public void run2(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService us=(UserService) ac.getBean("userService"); us.sayHello(); }
2.關(guān)于bean管理常用屬性
1. @Component:組件.(作用在類上) 最原始的注解,所有需要注解的類都寫這個(gè)沒問(wèn)題,他是通用的
2. Spring中提供@Component的三個(gè)衍生注解:(功能目前來(lái)講是一致的)
* @Controller -- 作用在WEB層
* @Service -- 作用在業(yè)務(wù)層
* @Repository -- 作用在持久層
* 說(shuō)明:這三個(gè)注解是為了讓標(biāo)注類本身的用途清晰,Spring在后續(xù)版本會(huì)對(duì)其增強(qiáng)
3. 屬性注入的注解(說(shuō)明:使用注解注入的方式,可以不用提供set方法)
* 如果是注入的普通類型,可以使用value注解
* @Value -- 用于注入普通類型
* 如果注入的是對(duì)象類型,使用如下注解
* @Autowired -- 默認(rèn)按類型進(jìn)行自動(dòng)裝配 匹配的是類型,與注入類的類名無(wú)關(guān)
* 如果想按名稱注入
* @Qualifier -- 強(qiáng)制使用名稱注入 必須與Autowired一起用,指定類名,與注入的類名有關(guān)
* @Resource -- 相當(dāng)于@Autowired和@Qualifier一起使用
* 強(qiáng)調(diào):Java提供的注解
* 屬性使用name屬性
4. Bean的作用范圍注解
* 注解為@Scope(value="prototype"),作用在類上。值如下:
* singleton -- 單例,默認(rèn)值
* prototype -- 多例
5. Bean的生命周期的配置(了解)
* 注解如下:
* @PostConstruct -- 相當(dāng)于init-method
* @PreDestroy -- 相當(dāng)于destroy-method
1.演示屬性對(duì)象注解
條件:采用掃描的方式將屬性(name)和對(duì)象(userDaoImpl)注入到業(yè)務(wù)層中
1)持久層開啟注解掃描Repository
//@Component(value="userDao")通用類注解 @Repository(value="ud") public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("保存客戶。。"); } }
2)業(yè)務(wù)層針對(duì)屬性和對(duì)象提供注解
package com.clj.demo1; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * 組件注解,可以用來(lái)標(biāo)記當(dāng)前的類 * 類似<bean id="userService" class="com.clj.demo1.UserServiceImpl"> * value表示給該類起個(gè)別名 */ //@Scope(value="grototype")多列的(singletype為單列) @Component(value="userService") public class UserServiceImpl implements UserService{ //屬性注解:相當(dāng)于給name屬性注入指定的字符串,setName方法可以省略不寫 @Value(value="佳先森") private String name; /** * 引用注入方式一:Autowired() * 引用注入方式二:Autowired()+Qualifier * 引用注入方式三:@Resource(name="userDao") java方式,按名稱識(shí)別注入 */ //Autowired()按類型自動(dòng)裝配注入(缺點(diǎn):因?yàn)槭前搭愋推ヅ洌圆皇呛軠?zhǔn)確) @Autowired() @Qualifier(value="ud") //按名稱注入,得與Autowired一起用,兩者一起能指定類 private UserDao userDao; //注意Qualifier中的value是指定UserDaoImpl類名頂上的注解名,也可以指定配置文件中bean的id名 /*public void setName(String name) { this.name = name; }*/ @Override public void sayHello() { System.out.println("Hello spring"+name); userDao.save(); } //@PostConstruct標(biāo)簽用于action生命周期中初始化的注解 @PostConstruct public void init(){ System.out.println("初始化..."); } }
3)配置文件只需要開啟全部掃描即可
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 開啟注解掃面 :base-package指定掃面對(duì) 包--> <context:component-scan base-package="com.clj.demo1"/> </beans>
注意:至于集合還是推薦使用配置文件方式
2.Spring框架整合JUnit單元測(cè)試
1)添加單元測(cè)試所需依賴包spring-test.jar
注意:基于myeclipes自帶Junit環(huán)境,但是有時(shí)因?yàn)榘姹締?wèn)題,可能需要比較新的Junit環(huán)境,這里我在網(wǎng)上下了一個(gè)教新的 Junit-4.9的jar包,如果myeclipes較新的話無(wú)須考慮
2)編寫測(cè)試類,添加相對(duì)應(yīng)的注解
@RunWith與@ContextConfiguration(此是用于加載配置文件,因?yàn)槟J(rèn)從WebRoot路徑為一級(jí)目錄,加上此是認(rèn)定src為一級(jí)目錄)
package com.clj.demo2; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.clj.demo1.UserService; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo2 { @Resource(name="userService") private UserService userService; @Test public void run1(){ userService.sayHello(); } }
六.spring框架之AOP
1.什么是AOP
* 在軟件業(yè),AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,功能模塊化
* AOP是一種編程范式,隸屬于軟工范疇,指導(dǎo)開發(fā)者如何組織程序結(jié)構(gòu)
* AOP最早由AOP聯(lián)盟的組織提出的,制定了一套規(guī)范.Spring將AOP思想引入到框架中,必須遵守AOP聯(lián)盟的規(guī)范
* 通過(guò)預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)
* AOP是OOP的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型
* 利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率
AOP采取橫向抽取機(jī)制,取代了傳統(tǒng)縱向繼承體系重復(fù)性代碼(性能監(jiān)視、事務(wù)管理、安全檢查、緩存)
2. 為什么要學(xué)習(xí)AOP
* 可以在不修改源代碼的前提下,對(duì)程序進(jìn)行增強(qiáng)?。。楣潭ǖ姆椒ㄉ梢粋€(gè)代理,在訪問(wèn)該方法之前,先進(jìn)入代理,在代理中,可以編寫更多的功能,使之方法的功能更強(qiáng),使得程序進(jìn)行增 強(qiáng))
Aop:面向切面編程,將一切事模塊化,每個(gè)模塊比較獨(dú)立,模塊可以共用(相同的),不同的格外自定義。用此替代傳統(tǒng)的面向縱向編程,提高程序的可重用性
3.AOP的實(shí)現(xiàn)(實(shí)現(xiàn)原理)
Aop的實(shí)現(xiàn)包含兩種代理方式<1>實(shí)現(xiàn)類接口:采用JDK動(dòng)態(tài)代理<2>未實(shí)現(xiàn)類接口:采用CGLIB動(dòng)態(tài)代理
1.實(shí)現(xiàn)JDK動(dòng)態(tài)代理
1)定義持久層接口實(shí)現(xiàn)類
package com.clj.demo3; public interface UserDao { public void save(); public void update(); }
package com.clj.demo3; public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("保存用戶"); } @Override public void update() { System.out.println("修改用戶"); } }
2)定義JDK動(dòng)態(tài)代理工具類
此工具類是在執(zhí)行持久層save方法時(shí)增加一些功能,在開發(fā)中做到在不更改源碼情況下增強(qiáng)某方法
package com.clj.demo3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 使用JDK的方式生成代理對(duì)象(演示AOP原理) * @author Administrator * */ public class MyProxyUtils { public static UserDao getProxy(final UserDao dao){ //使用Proxy類生成代理對(duì)象 UserDao proxy=(UserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader() , dao.getClass().getInterfaces(),new InvocationHandler() { //只要代理對(duì)象一執(zhí)行,invoke方法就會(huì)執(zhí)行一次 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy代表當(dāng)前代理對(duì)象 //method當(dāng)前對(duì)象執(zhí)行的方法 //args封裝的參數(shù) //讓到類的save或者update方法正常執(zhí)行下去 if("save".equals(method.getName())){ System.out.println("執(zhí)行了保存"); //開啟事務(wù) } return method.invoke(dao, args); } }); return proxy; } }
3)測(cè)試
package com.clj.demo3; import org.junit.Test; public class Demo1 { @Test public void run1(){ //獲取目標(biāo)對(duì)象 UserDao dao=new UserDaoImpl(); dao.save(); dao.update(); System.out.println("==============="); //使用工具類,獲取到代理對(duì)象 UserDao proxy=MyProxyUtils.getProxy(dao); //調(diào)用代理對(duì)象的方法 proxy.save(); proxy.update(); } }
2.實(shí)現(xiàn)CGLIB技術(shù)
1)定義持久層,此時(shí)沒有接口
package com.clj.demo4; public class BookDaoImpl { public void save(){ System.out.println("保存圖書"); } public void update(){ System.out.println("修改圖書"); } }
2)編寫工具類
package com.clj.demo4; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /** * Cglib代理方式實(shí)現(xiàn)原理 * @author Administrator * */ public class MyCglibUtils { /** * 使用CGLIB方式生成代理對(duì)象 * @return */ public static BookDaoImpl getProxy(){ Enhancer enhancer=new Enhancer(); //設(shè)置父類 enhancer.setSuperclass(BookDaoImpl.class); //設(shè)置回調(diào)函數(shù) enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] objs, MethodProxy methodProxy) throws Throwable { if(method.getName().equals("save")){ System.out.println("我保存了"); System.out.println("代理對(duì)象執(zhí)行了"); } return methodProxy.invokeSuper(obj, objs);//是方法執(zhí)行下去 } }); //生成代理對(duì)象 BookDaoImpl proxy=(BookDaoImpl) enhancer.create(); return proxy; } }
3)編寫測(cè)試類
package com.clj.demo4; import org.junit.Test; public class Demo1 { @Test public void run1(){ //目標(biāo)對(duì)象 BookDaoImpl dao=new BookDaoImpl(); dao.save(); dao.update(); System.out.println("=========="); BookDaoImpl proxy=MyCglibUtils.getProxy(); proxy.save(); proxy.update(); } }
3、Spring基于AspectJ的AOP的開發(fā)(配置文件方式)
1)部署環(huán)境,導(dǎo)入相對(duì)應(yīng)的jar包
2)創(chuàng)建配置文件,并引入AOP約束
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
3)創(chuàng)建接口和實(shí)現(xiàn)類
package com.clj.demo5; public interface CustomerDao { public void save(); public void update(); }
package com.clj.demo5; /** * 采用配置文件的方式 詮釋AOP * @author Administrator * */ public class CustomerDaoImpl implements CustomerDao { @Override public void save() { //模擬異常 //int a=10/0; System.out.println("保存客戶了啊"); } @Override public void update() { // TODO Auto-generated method stub System.out.println("更新客戶了啊"); } }
4)定義切面類
package com.clj.demo5; import org.aspectj.lang.ProceedingJoinPoint; /** * 切面類:切入點(diǎn)+通知 * @author Administrator * */ public class MyAspectXml { /** * 通知(具體的增強(qiáng)) */ public void log(){ System.out.println("記錄日志"); } /** * 方法執(zhí)行成功或者異常都會(huì)執(zhí)行 */ public void after(){ System.out.println("最終通知"); } /** * 方法執(zhí)行之后,執(zhí)行后置通知,如果程序出現(xiàn)異常,后置通知不會(huì)執(zhí)行 */ public void afterReturn(){ System.out.println("后置通知"); } /** * 方法執(zhí)行之后,如果程序有異常,才會(huì)執(zhí)行異常通知 */ public void afterThrowing(){ System.out.println("異常通知"); } /** * 環(huán)繞通知:方法執(zhí)行之前和方法執(zhí)行之后進(jìn)行通知, * 默認(rèn)情況下,目標(biāo)對(duì)象的方法不能執(zhí)行的,需要手動(dòng)讓目標(biāo)對(duì)象執(zhí)行 */ public void around(ProceedingJoinPoint joinPoint){ System.out.println("環(huán)繞通知1"); //手動(dòng)讓目標(biāo)對(duì)象的方法執(zhí)行 try { joinPoint.proceed(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("環(huán)繞通知2"); } }
5)注入實(shí)現(xiàn)類和切面類
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --> <!-- 配置客戶的dao --> <bean id="customerDao" class="com.clj.demo5.CustomerDaoImpl"/> <!-- 編寫切面類配置好 --> <bean id="myAspectXml" class="com.clj.demo5.MyAspectXml"/> <!-- 配置AOP --> <aop:config> <!-- 配置切面類:切入點(diǎn)+通知 (類型)--> <aop:aspect ref="myAspectXml"> <!-- 配置前置通知,save方法執(zhí)行之前,增強(qiáng)方法會(huì)執(zhí)行 --> <!-- 切入點(diǎn)表達(dá)式:execution(public void com.clj.demo5.CustomerDaoImpl.save()) --> <!-- 切入點(diǎn)表達(dá)式: 1.execution()固定的,必寫 2.public可以省略不寫 3.返回值 必寫,嚴(yán)格根據(jù)切入點(diǎn)方法而定,否則增強(qiáng)方法不會(huì)執(zhí)行,可以用*代替,表示任意的返回值 4.包名 必寫,可以用*代替(如:*..*(默認(rèn)所有包); com.clj.*) 5.類名 必寫,可以部分用*(如*DaoImpl表示以'DaoImpl'結(jié)尾的持久層實(shí)現(xiàn)類),但不建議用*代替整個(gè)類名 6.方法 必寫,可以部分用*(如save*表示以'save'開頭的方法),但不建議用*代替整個(gè)類名 7.方法參數(shù) 根據(jù)實(shí)際方法而定,可以用'..'表示有0或者多個(gè)參數(shù) --> <!-- <aop:before method="log" pointcut="execution(public void com.clj.*.CustomerDaoImpl.save(..))"/> --> <aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save*(..))"/> </aop:aspect> </aop:config> </beans>
6)測(cè)試
package com.clj.demo5; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo1 { @Resource(name="customerDao") private CustomerDao customerDao; @Test public void run(){ customerDao.save(); customerDao.update(); } }
擴(kuò)展:切面類升級(jí)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --> <bean id="myAspectXml" class="com.clj.demo5.MyAspectXml"/> <aop:config> <aop:aspect ref="myAspectXml"> <!-- 配置最終通知 <aop:after method="after" pointcut="execution(* *..*.*DaoImpl.save*(..))"/>--> <!-- 配置后置通知 <aop:after-returning method="afterReturn" pointcut="execution(* *..*.*DaoImpl.save*(..))"/>--> <!-- 配置異常通知 <aop:after-throwing method="afterThrowing" pointcut="execution(* *..*.*DaoImpl.save*(..))"/>--> <aop:around method="around" pointcut="execution(* *..*.*DaoImpl.update*(..))"/> </aop:aspect> </aop:config> </beans>
4、Spring框架AOP之注解方式
1)創(chuàng)建接口和實(shí)現(xiàn)類
package com.clj.demo1; public interface CustomerDao { public void save(); public void update(); }
package com.clj.demo1; public class CustomerDaoImpl implements CustomerDao{ @Override public void save() { // TODO Auto-generated method stub System.out.println("保存客戶.."); } @Override public void update() { // TODO Auto-generated method stub System.out.println("更新客戶"); } }
2)定義切面類
package com.clj.demo1; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; /** * 注解方式的切面類 * @Aspect表示定義為切面類 */ @Aspect public class MyAspectAnno { //通知類型:@Before前置通知(切入點(diǎn)的表達(dá)式) @Before(value="execution(public * com.clj.demo1.CustomerDaoImpl.save())") public void log(){ System.out.println("記錄日志。。"); } //引入切入點(diǎn) @After(value="MyAspectAnno.fun()") public void after(){ System.out.println("執(zhí)行之后"); } @Around(value="MyAspectAnno.fun()") public void around(ProceedingJoinPoint joinPoint){ System.out.println("環(huán)繞通知1"); try { //讓目標(biāo)對(duì)象執(zhí)行 joinPoint.proceed(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("環(huán)繞通知2"); } //自定義切入點(diǎn) @Pointcut(value="execution(public * com.clj.demo1.CustomerDaoImpl.save())") public void fun(){ } }
3)配置切面類和實(shí)現(xiàn)類,并開啟自動(dòng)代理
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 開啟自動(dòng)注解代理--> <aop:aspectj-autoproxy/> <!-- 配置目標(biāo)對(duì)象 --> <bean id="customerDao" class="com.clj.demo1.CustomerDaoImpl"/> <!-- 配置切面類 --> <bean id="myAspectAnno" class="com.clj.demo1.MyAspectAnno"/> </beans>
spring提供了JDBC模板:JdbcTemplate類
1.快速搭建
1)部署環(huán)境
這里在原有的jar包基礎(chǔ)上,還要添加關(guān)乎jdbc的jar包,這里使用的是mysql驅(qū)動(dòng)
2)配置內(nèi)置連接池,將連接數(shù)據(jù)庫(kù)程序交給框架管理,并配置Jdbc模板類
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 先配置連接池(內(nèi)置) --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置JDBC的模板類--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
3)測(cè)試
package com.clj.demo2; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import javax.annotation.Resource; import org.apache.commons.dbcp.BasicDataSource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.cglib.beans.BeanMap; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * 測(cè)試JDBC的模板類,使用IOC的方式 * @author Administrator * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo2 { @Resource(name="jdbcTemplate") private JdbcTemplate jdbcTemplate; /** * 插入 */ @Test public void run1(){ String sql="insert into t_account values(null,?,?)"; jdbcTemplate.update(sql,"李釔林",10000); } /** * 更新 */ @Test public void run2(){ String sql="update t_account set name=? where id=?"; jdbcTemplate.update(sql,"李釔林",1); } /** * 刪除 */ @Test public void run3(){ String sql="delete from t_account where id=?"; jdbcTemplate.update(sql,4); } /** * 測(cè)試查詢,通過(guò)主鍵來(lái)查詢一條記錄 */ @Test public void run4(){ String sql="select * from t_account where id=?"; Account ac=jdbcTemplate.queryForObject(sql, new BeanMapper(),1); System.out.println(ac); } /** * 查詢所有 */ @Test public void run5(){ String sql="select * from t_account"; List<Account> ac=jdbcTemplate.query(sql,new BeanMapper()); System.out.println(ac); } } /** * 定義內(nèi)部類(手動(dòng)封裝數(shù)據(jù)(一行一行封裝數(shù)據(jù),用于查詢所有) * @author Administrator * */ class BeanMapper implements RowMapper<Account>{ @Override public Account mapRow(ResultSet rs, int rowNum) throws SQLException { Account ac=new Account(); ac.setId(rs.getInt("id")); ac.setName(rs.getString("name")); ac.setMoney(rs.getDouble("money")); return ac; } }
2、配置開源連接池
一般現(xiàn)在企業(yè)都是用一些主流的連接池,如c3p0和dbcp
首先配置dbcp
1)導(dǎo)入dbcp依賴jar包
2)編寫配置文件
<!-- 配置DBCP開源連接池--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean>
將模板類中引入的內(nèi)置類datasource改為開源連接池的
3)編寫測(cè)試類
配置c3p0
1)導(dǎo)入c3p0依賴jar包
2)配置c3p0
<!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean>
將模板類中引入的內(nèi)置類datasource改為開源連接池的
3)編寫測(cè)試類
1、什么是事務(wù)
數(shù)據(jù)庫(kù)事務(wù)(Database Transaction) ,是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作,要么完全地執(zhí)行,要么完全地不執(zhí)行。 事務(wù)處理可以確保除非事務(wù)性單元內(nèi)的所有操作都成功完成,否則不會(huì)永久更新面向數(shù)據(jù)的資源。通過(guò)將一組相關(guān)操作組合為一個(gè)要么全部成功要么全部失敗的單元,可以簡(jiǎn)化錯(cuò)誤恢復(fù)并使應(yīng)用程序更加可靠。一個(gè)邏輯工作單元要成為事務(wù),必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。事務(wù)是數(shù)據(jù)庫(kù)運(yùn)行中的邏輯工作單位,由DBMS中的事務(wù)管理子系統(tǒng)負(fù)責(zé)事務(wù)的處理。
2、怎么解決事務(wù)安全性問(wèn)題
讀問(wèn)題解決,設(shè)置數(shù)據(jù)庫(kù)隔離級(jí)別;寫問(wèn)題解決可以使用 悲觀鎖和樂觀鎖的方式解決
3、快速開發(fā)
方式一:調(diào)用模板類,將模板注入持久層
1)編寫相對(duì)應(yīng)的持久層和也外層,這里省略接口
package com.clj.demo3; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{ // 方式一:將jdbc模板類注入到配置文件中,直接在持久層寫模板類 private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void outMoney(String out, double money) { String sql="update t_account set money=money-? where name=?"; jdbcTemplate().update(sql,money,out); } public void inMoney(String in, double money) { String sql="update t_account set money=money+? where name=?"; jdbcTemplate().update(sql,money,in); } }
package com.clj.demo4; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; public class AccountServiceImpl implements AccountService{ //采用的是配置文件注入方式,必須提供set方法 private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void pay(String out, String in, double money) { // TODO Auto-generated method stub accountDao.outMoney(out, money); int a=10/0; accountDao.inMoney(in, money); } }
2)配置相對(duì)應(yīng)的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置JDBC的模板類 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置業(yè)務(wù)層和持久層 --> <bean id="accountService" class="com.clj.demo3.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao" class="com.clj.demo3.AccountDaoImpl"> <!-- 注入模板類--> <property name="jdbcTemplate" ref="jdbcTemplate"/> <property name="dataSource" ref="dataSource"/> </bean> </beans>
3)測(cè)試類
package com.clj.demo3; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo1 { @Resource(name="accountService") private AccountService accountService; @Test public void Demo1(){ //調(diào)用支付的方法 accountService.pay("佳先森","李釔林",100); } }
方式二:持久層繼承JdbcDaoSupport接口,此接口封裝了模板類jdbcTemplate
1)編寫配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置業(yè)務(wù)層和持久層 --> <bean id="accountService" class="com.clj.demo3.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao" class="com.clj.demo3.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
2)更改持久層
package com.clj.demo3; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{ //方式一:將jdbc模板類注入到配置文件中,直接在持久層寫模板類 // private JdbcTemplate jdbcTemplate; // public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { // this.jdbcTemplate = jdbcTemplate; // } //方式二:持久層繼承JdbcDaoSupport,它里面封轉(zhuǎn)了模板類,配置文件持久層無(wú)需注入模板類,也不需要配置模板類 public void outMoney(String out, double money) { //jdbcTemplate.update(psc); String sql="update t_account set money=money-? where name=?"; this.getJdbcTemplate().update(sql,money,out); } public void inMoney(String in, double money) { String sql="update t_account set money=money+? where name=?"; this.getJdbcTemplate().update(sql,money,in); } }
3)更改業(yè)務(wù)層
package com.clj.demo4; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; public class AccountServiceImpl implements AccountService{ //采用的是配置文件注入方式,必須提供set方法 private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void pay(String out, String in, double money) { // TODO Auto-generated method stub accountDao.outMoney(out, money); int a=10/0; accountDao.inMoney(in, money); } }
4)測(cè)試類和上述一樣
4、spring事務(wù)管理
Spring為了簡(jiǎn)化事務(wù)管理的代碼:提供了模板類 TransactionTemplate,手動(dòng)編程的方式來(lái)管理事務(wù),只需要使用該模板類即可??!
1、手動(dòng)編程方式事務(wù)(了解原理)
1)快速部署,搭建配置文件,配置事務(wù)管理和事務(wù)管理模板,并在持久層注入事務(wù)管理模板
配置事務(wù)管理器
<!-- 配置平臺(tái)事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
配置事務(wù)管理模板
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean>
將管理模板注入業(yè)務(wù)層
<bean id="accountService" class="com.clj.demo3.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean>
全部代碼:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置業(yè)務(wù)層和持久層 --> <bean id="accountService" class="com.clj.demo3.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean> <bean id="accountDao" class="com.clj.demo3.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置平臺(tái)事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 手動(dòng)編碼方式,提供了模板類,使用該類管理事務(wù)比較簡(jiǎn)單--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean> </beans>
2)在業(yè)務(wù)層使用模板事務(wù)管理
package com.clj.demo3; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; public class AccountServiceImpl implements AccountService{ //采用的是配置文件注入方式,必須提供set方法 private AccountDao accountDao; //注入事務(wù)模板類 private TransactionTemplate transactionTemplate; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } /** * 轉(zhuǎn)賬的方法 */ public void pay(final String out,final String in, final double money) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { //事務(wù)的執(zhí)行,如果沒有問(wèn)題,提交,如果楚翔異常,回滾 protected void doInTransactionWithoutResult(TransactionStatus arg0) { // TODO Auto-generated method stub accountDao.outMoney(out, money); int a=10/0; accountDao.inMoney(in, money); } }); } }
3)測(cè)試類和上一致
package com.clj.demo4; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class Demo2 { @Resource(name="accountService") private AccountService accountService; @Test public void Demo1(){ //調(diào)用支付的方法 accountService.pay("佳先森","李釔林",100); } }
申明式事務(wù)有兩種方式:基于AspectJ的XML方式;基于AspectJ的注解方式
1、XML方式
1)配置配置文件
需要配置平臺(tái)事務(wù)管理
<!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置平臺(tái)事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
配置事務(wù)增強(qiáng)
<tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 給方法設(shè)置數(shù)據(jù)庫(kù)屬性(隔離級(jí)別,傳播行為) --> <!--propagation事務(wù)隔離級(jí)別:一般采用默認(rèn)形式:tx:method可以設(shè)置多個(gè) --> <tx:method name="pay" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
aop切面類
<aop:config> <!-- aop:advisor,是spring框架提供的通知--> <aop:advisor advice-ref="myAdvice" pointcut="execution(public * com.clj.demo4.AccountServiceImpl.pay(..))"/> </aop:config>
全部代碼
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置平臺(tái)事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 申明式事務(wù)(采用XML文件的方式) --> <!-- 先配置通知 --> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 給方法設(shè)置數(shù)據(jù)庫(kù)屬性(隔離級(jí)別,傳播行為) --> <!--propagation事務(wù)隔離級(jí)別:一般采用默認(rèn)形式:tx:method可以設(shè)置多個(gè) --> <tx:method name="pay" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置AOP:如果是自己編寫的AOP,使用aop:aspect配置,使用的是Spring框架提供的通知 --> <aop:config> <!-- aop:advisor,是spring框架提供的通知--> <aop:advisor advice-ref="myAdvice" pointcut="execution(public * com.clj.demo4.AccountServiceImpl.pay(..))"/> </aop:config> <!-- 配置業(yè)務(wù)層和持久層 --> <bean id="accountService" class="com.clj.demo4.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao" class="com.clj.demo4.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
2)編寫持久層和業(yè)務(wù)層(省略接口)
package com.clj.demo5; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{ //方式一:將jdbc模板類注入到配置文件中,直接在持久層寫模板類 // private JdbcTemplate jdbcTemplate; // public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { // this.jdbcTemplate = jdbcTemplate; // } //方式二:持久層繼承JdbcDaoSupport,它里面封轉(zhuǎn)了模板類,配置文件持久層無(wú)需注入模板類,也不需要配置模板類 public void outMoney(String out, double money) { //jdbcTemplate.update(psc); String sql="update t_account set money=money-? where name=?"; this.getJdbcTemplate().update(sql,money,out); } public void inMoney(String in, double money) { String sql="update t_account set money=money+? where name=?"; this.getJdbcTemplate().update(sql,money,in); } }
package com.clj.demo5; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate;public class AccountServiceImpl implements AccountService{ //采用的是配置文件注入方式,必須提供set方法 private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void pay(String out, String in, double money) { // TODO Auto-generated method stub accountDao.outMoney(out, money); int a=10/0; accountDao.inMoney(in, money); } }
3)測(cè)試類
package com.clj.demo4; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class Demo2 { @Resource(name="accountService") private AccountService accountService; @Test public void Demo1(){ //調(diào)用支付的方法 accountService.pay("佳先森","李釔林",100); } }
2、注解方式
1)配置配置文件
配置事務(wù)管理
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
開啟注釋事務(wù)
<!-- 開啟事務(wù)的注解 --> <tx:annotation-driven transaction-manager="transactionManager"/>
全部代碼
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置C3P0開源連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置平臺(tái)事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 開啟事務(wù)的注解 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 配置業(yè)務(wù)層和持久層 --> <bean id="accountService" class="com.clj.demo5.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao" class="com.clj.demo5.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
2)業(yè)務(wù)層增加@Transactional
package com.clj.demo5; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; //在當(dāng)前類加此注解表示當(dāng)前類所有的全部都有事務(wù) @Transactional public class AccountServiceImpl implements AccountService{ //采用的是配置文件注入方式,必須提供set方法 private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void pay(String out, String in, double money) { // TODO Auto-generated method stub accountDao.outMoney(out, money); int a=10/0; accountDao.inMoney(in, money); } }
3)持久層不變
package com.clj.demo5; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{ //方式一:將jdbc模板類注入到配置文件中,直接在持久層寫模板類 // private JdbcTemplate jdbcTemplate; // public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { // this.jdbcTemplate = jdbcTemplate; // } //方式二:持久層繼承JdbcDaoSupport,它里面封轉(zhuǎn)了模板類,配置文件持久層無(wú)需注入模板類,也不需要配置模板類 public void outMoney(String out, double money) { //jdbcTemplate.update(psc); String sql="update t_account set money=money-? where name=?"; this.getJdbcTemplate().update(sql,money,out); } public void inMoney(String in, double money) { String sql="update t_account set money=money+? where name=?"; this.getJdbcTemplate().update(sql,money,in); } }
4)測(cè)試類
package com.clj.demo5; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext3.xml") public class Demo3 { @Resource(name="accountService") private AccountService accountService; @Test public void Demo1(){ //調(diào)用支付的方法 accountService.pay("佳先森","李釔林",100); } }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Spring框架怎么用”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。