Spring框架是由於軟件開發的複雜性而創建的。 Spring使用的是基本的JavaBean來完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限於服務器端的開發。從簡單性、可測試性和松耦合性角度而言,絕大部分Java應用都可以從Spring中受益。 Spring是一個輕量級控制反轉(IoC)和麵向切面(AOP)的容器框架。
◆目的:解決企業應用開發的複雜性
◆功能:使用基本的JavaBean代替EJB,並提供了更多的企業應用功能
◆範圍:任何Java應用
控制反轉(Inversion of Control,英文縮寫為IoC)把創建對象的權利交給框架,是框架的重要特徵,並非面向對象編程的專用術語。它包括依賴注入和依賴查找。傳統的業務層,當需要資源時就在該業務層new資源,這樣耦合性(程序之間相互依賴關聯)較高。現在將new的部分交給spring,做到高內聚低耦合。簡而言之:原先是每當調用dao層或service層方法時,由app來new,現在是將new的權利交給spring,要什麼資源從spring中獲取!
1.下載框架所需的依賴jar包
spring官網為:http://spring.io/
下載jar包: http://repo.springsource.org/libs-release-local/org/springframework/spring
2.導入基本jar包
其實基本核心jar有beans;context;core;expression包,其他是依賴log4j日誌。當然spring的jar不止這些,後期慢慢加上。
3.配置log4j配置文件
日誌文件定義在src目錄下
### direct log messages to stdout ###log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target=System.errlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n### direct messages to file mylog.log ###log4j.appender.file=org.apache.log4j.FileAppenderlog4j.appender.file.File=c/:mylog.loglog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.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, stdout4.測試日誌文件是否部署成功
package com.clj.demo1;import org.apache.log4j.Logger;import org.junit.Test;/** * 演示日誌用法* @author Administrator * */public class Demo1 { //創建日誌類private Logger log=Logger.getLogger(Demo1.class); @Test public void run1(){ //可以將log4j.rootLogger屬性中的info改為off則不會再控制台顯示log.info("執行了"); }}5.定義一個接口和實現類
接口:
package com.clj.demo2;public interface UserService { public void sayHello();}實現類
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下,與日誌文件同目錄,導入相對應的約束,並將實現類註入到配置文件中,剛開始入門,使用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標籤1.id值唯一(必寫) 2.注意:class為實現類路徑,不是接口(必寫) 3.init-method核心方法執行之前初始化工作(選寫) 4.destroy-method核心方法執行之後初始化工作(選寫)--> <bean id="userService" init-method="init" destroy-method="destory"> <property name="name" value="佳先森"></property> </bean></beans>
7.測試
public class Demo1 { /** * 原始方式*/ @Test public void run(){ //創建實現類UserServiceImpl s=new UserServiceImpl(); s.setName("佳先森"); s.sayHello(); } /** * 老的工廠版本BeanFactory * 舊的工廠不會創建配置文件對象*/ @Test public void run2(){ BeanFactory factory=new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); UserService us=(UserService)factory.getBean("userService"); us.sayHello(); } /** * 使用spring框架IOC方式* 新版本factory創建啟動服務器會創建配置文件對象,再次調用時無需加載工廠*/ @Test public void run3(){ //創建工廠,加載核心配置文件(ClassPathXmlApplicationContext從src下找) ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); //從工廠中獲取到對象(配置文件中的id值,這裡用了多態) UserService usi=(UserService) ac.getBean("userService"); //調用對象的方法執行usi.sayHello(); } /** * 演示destroy-method方法* bean摧毀方法不會自動執行* 除非scope= singleton或者web容器中會自動調用,但是main函數或測試用例需要手動調用(需要使用ClassPathXmlApplicationContext的close()方法) */ @Test public void run4(){ //創建工廠,加載核心配置文件(ClassPathXmlApplicationContext從src下找) ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); //從工廠中獲取到對象(配置文件中的id值,這裡用了多態) UserService usi=(UserService) ac.getBean("userService"); //調用對象的方法執行usi.sayHello(); //ApplicationContext實現類提供close方法,將工廠關閉就可執行destory-method方法ac.close(); }}其中舊工廠與新工廠的區別
* BeanFactory和ApplicationContext的區別
* BeanFactory -- BeanFactory採取延遲加載,第一次getBean時才會初始化Bean
* ApplicationContext -- 在加載applicationContext.xml時候就會創建具體的Bean對象的實例,還提供了一些其他的功能
* 事件傳遞
* Bean自動裝配
* 各種不同應用層的Context實現
總結:這是個最基本的demo,是將實現類配置到了spring配置文件中,每次啟動服務器時,就會加載配置文件,從而實例化了實現類
1、什麼是依賴注入?
Spring 能有效地組織J2EE應用各層的對象。不管是控制層的Action對象,還是業務層的Service對象,還是持久層的DAO對象,都可在Spring的管理下有機地協調、運行。 Spring將各層的對像以松耦合的方式組織在一起,Action對象無須關心Service對象的具體實現,Service對象無須關心持久層對象的具體實現,各層對象的調用完全面向接口。當系統需要重構時,代碼的改寫量將大大減少。依賴注入讓bean與bean之間以配置文件組織在一起,而不是以硬編碼的方式耦合在一起。理解依賴注入
依賴注入(Dependency Injection)和控制反轉(Inversion of Control)是同一個概念。具體含義是:當某個角色(可能是一個Java實例,調用者)需要另一個角色(另一個Java實例,被調用者)的協助時,在傳統的程序設計過程中,通常由調用者來創建被調用者的實例。但在Spring裡,創建被調用者的工作不再由調用者來完成,因此稱為控制反轉;創建被調用者實例的工作通常由Spring容器來完成,然後注入調用者,因此也稱為依賴注入。
不管是依賴注入,還是控制反轉,都說明Spring採用動態、靈活的方式來管理各種對象。對象與對象之間的具體實現互相透明。
2. IOC和DI的概念
* IOC -- Inverse of Control,控制反轉,將對象的創建權反轉給Spring! !
* DI -- Dependency Injection,依賴注入,在Spring框架負責創建Bean對象時,動態的將依賴對象注入到Bean組件中! !
3.演示
對於類成員變量,常用的注入方式有兩種
屬性set方法注入和構造方法注入
先演示第一種:屬性set方法注入
1)持久層
package com.clj.demo3;public class CustomerDaoImpl { public void save(){ System.out.println("我是持久層的Dao"); }}2)業務層
注意:此時是想將持久層注入到業務層,將創建持久層實例權利交給框架,條件是業務層必須提供持久層的成員屬性和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("我是業務層的service..."); //1.原始方式//new CustomerDaoImpl().save(); //2.spring 之IOC方式customerDao.save(); }}3)配置文件配置
<!-- 演示依賴注入--> <bean id="customerDao"/> <bean id="customerService"> <!-- 將Dao注入到service層--> <property name="customerDao" ref="customerDao"></property> </bean>
4)測試
/** * spring 依賴注入方式* 將dao層注入到service層*/ @Test public void run2(){ //創建工廠,加載配置文件,customerService被創建,從而也創建了customerDao ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); CustomerServiceImpl csi=(CustomerServiceImpl) context.getBean("customerService"); csi.save(); }第二種:構造方法注入
1)pojo類並提供構造方法
package com.clj.demo4;/** * 演示的構造方法的注入方式* @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)配置文件配置
<!-- 演示構造方法注入方式--> <bean id="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)測試
@Test public void run1(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); Car1 car=(Car1) ac.getBean("car1"); System.out.println(car); }拓展:構造方法之將一個對象注入到另一個對像中
1)pojo類:目的:將上列中的車注入到人類,使之成為其中一個屬性,則必須在此類中提供車的成員屬性,並提供有參構造方法
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)配置文件
<!-- 構造方法之將一個對象注入到另一個對象--> <bean id="person"> <constructor-arg name="name" value="佳先森"/> <constructor-arg name="car1" ref="car1"/> </bean>
4.如何注入集合數組
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"> <!-- 數組--> <property name="arrs"> <list> <value>數字1</value> <value>數字2</value> <value>數字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)測試
/** * 測試注入集合*/ @Test public void run3(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); User user= (User) ac.getBean("user"); System.out.println(user); }5.怎麼分模塊開發
在主配置文件加入<import>標籤(假如此時在com.clj.test包下定義了一個配置文件applicationContext2.xml)
<!-- 分模塊開發之引入其他配置文件--> <import resource="com/clj/test/applicationContext2.xml"/>
1、入門
1).導入jar包
除了先前6個包,玩註解還需一個spring-aop包
2).持久層和實現層(這裡忽略接口)
持久層
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("保存客戶。。"); }}業務層
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).定義配置文件
此時約束條件需添加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指定掃面對包--> <context:component-scan base-package="com.clj.demo1"/></beans>
4)在實現類中添加註解
/** * 組件註解,可以用來標記當前的類* 類似<bean id="userService"> * value表示給該類起個別名*/@Component(value="userService")public class UserServiceImpl implements UserService{ //省略}5)編寫測試
/** * 註解方式*/ @Test public void run2(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService us=(UserService) ac.getBean("userService"); us.sayHello(); }2.關於bean管理常用屬性
1. @Component:組件.(作用在類上) 最原始的註解,所有需要註解的類都寫這個沒問題,他是通用的
2. Spring中提供@Component的三個衍生註解:(功能目前來講是一致的)
* @Controller -- 作用在WEB層
* @Service -- 作用在業務層
* @Repository -- 作用在持久層
* 說明:這三個註解是為了讓標註類本身的用途清晰,Spring在後續版本會對其增強
3. 屬性注入的註解(說明:使用註解注入的方式,可以不用提供set方法)
* 如果是注入的普通類型,可以使用value註解
* @Value -- 用於注入普通類型
* 如果注入的是對像類型,使用如下註解
* @Autowired -- 默認按類型進行自動裝配匹配的是類型,與註入類的類名無關
* 如果想按名稱注入
* @Qualifier -- 強制使用名稱注入必須與Autowired一起用,指定類名,與註入的類名有關
* @Resource -- 相當於@Autowired和@Qualifier一起使用
* 強調:Java提供的註解
* 屬性使用name屬性
4. Bean的作用範圍註解
* 註解為@Scope(value="prototype"),作用在類上。值如下:
* singleton -- 單例,默認值
* prototype -- 多例
5. Bean的生命週期的配置(了解)
* 註解如下:
* @PostConstruct -- 相當於init-method
* @PreDestroy -- 相當於destroy-method
1.演示屬性對象註解
條件:採用掃描的方式將屬性(name)和對象(userDaoImpl)注入到業務層中
1)持久層開啟註解掃描Repository
//@Component(value="userDao")通用類註解@Repository(value="ud")public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("保存客戶。。"); }}2)業務層針對屬性和對象提供註解
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;/** * 組件註解,可以用來標記當前的類* 類似<bean id="userService"> * value表示給該類起個別名*///@Scope(value="grototype")多列的(singletype為單列)@Component(value="userService")public class UserServiceImpl implements UserService{ //屬性註解:相當於給name屬性注入指定的字符串,setName方法可以省略不寫@Value(value="佳先森") private String name; /** * 引用注入方式一:Autowired() * 引用注入方式二:Autowired()+Qualifier * 引用注入方式三:@Resource(name="userDao") java方式,按名稱識別注入*/ //Autowired()按類型自動裝配注入(缺點:因為是按類型匹配,所以不是很準確) @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標籤用於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指定掃面對包--> <context:component-scan base-package="com.clj.demo1"/></beans>
注意:至於集合還是推薦使用配置文件方式
2.Spring框架整合JUnit單元測試
1)添加單元測試所需依賴包spring-test.jar
注意:基於myeclipes自帶Junit環境,但是有時因為版本問題,可能需要比較新的Junit環境,這裡我在網上下了一個教新的Junit-4.9的jar包,如果myeclipes較新的話無須考慮
2)編寫測試類,添加相對應的註解
@RunWith與@ContextConfiguration(此是用於加載配置文件,因為默認從WebRoot路徑為一級目錄,加上此是認定src為一級目錄)
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
* 在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,功能模塊化
* AOP是一種編程範式,隸屬於軟工範疇,指導開發者如何組織程序結構
* AOP最早由AOP聯盟的組織提出的,制定了一套規範.Spring將AOP思想引入到框架中,必須遵守AOP聯盟的規範
* 通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術
* AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型
* 利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率
AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性代碼(性能監視、事務管理、安全檢查、緩存)
2. 為什麼要學習AOP
* 可以在不修改源代碼的前提下,對程序進行增強! ! (為固定的方法生成一個代理,在訪問該方法之前,先進入代理,在代理中,可以編寫更多的功能,使之方法的功能更強,使得程序進行增強)
Aop:面向切面編程,將一切事模塊化,每個模塊比較獨立,模塊可以共用(相同的),不同的格外自定義。用此替代傳統的面向縱向編程,提高程序的可重用性
3.AOP的實現(實現原理)
Aop的實現包含兩種代理方式<1>實現類接口:採用JDK動態代理<2>未實現類接口:採用CGLIB動態代理
1.實現JDK動態代理
1)定義持久層接口實現類
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動態代理工具類
此工具類是在執行持久層save方法時增加一些功能,在開發中做到在不更改源碼情況下增強某方法
package com.clj.demo3;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 使用JDK的方式生成代理對象(演示AOP原理) * @author Administrator * */public class MyProxyUtils { public static UserDao getProxy(final UserDao dao){ //使用Proxy類生成代理對象UserDao proxy=(UserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader() , dao.getClass().getInterfaces(),new InvocationHandler() { //只要代理對像一執行,invoke方法就會執行一次public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy代表當前代理對象//method當前對象執行的方法//args封裝的參數//讓到類的save或者update方法正常執行下去if("save".equals(method.getName())){ System.out.println("執行了保存"); //開啟事務} return method.invoke(dao, args); } }); return proxy; }}3)測試
package com.clj.demo3;import org.junit.Test;public class Demo1 { @Test public void run1(){ //獲取目標對象UserDao dao=new UserDaoImpl(); dao.save(); dao.update(); System.out.println("==============="); //使用工具類,獲取到代理對象UserDao proxy=MyProxyUtils.getProxy(dao); //調用代理對象的方法proxy.save(); proxy.update(); }}2.實現CGLIB技術
1)定義持久層,此時沒有接口
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代理方式實現原理* @author Administrator * */public class MyCglibUtils { /** * 使用CGLIB方式生成代理對象* @return */ public static BookDaoImpl getProxy(){ Enhancer enhancer=new Enhancer(); //設置父類enhancer.setSuperclass(BookDaoImpl.class); //設置回調函數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("代理對象執行了"); } return methodProxy.invokeSuper(obj, objs);//是方法執行下去} }); //生成代理對象BookDaoImpl proxy=(BookDaoImpl) enhancer.create(); return proxy; }}3)編寫測試類
package com.clj.demo4;import org.junit.Test;public class Demo1 { @Test public void run1(){ //目標對象BookDaoImpl dao=new BookDaoImpl(); dao.save(); dao.update(); System.out.println("=========="); BookDaoImpl proxy=MyCglibUtils.getProxy(); proxy.save(); proxy.update(); }}3、Spring基於AspectJ的AOP的開發(配置文件方式)
1)部署環境,導入相對應的jar包
2)創建配置文件,並引入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)創建接口和實現類
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;/** * 切麵類:切入點+通知* @author Administrator * */public class MyAspectXml { /** * 通知(具體的增強) */ public void log(){ System.out.println("記錄日誌"); } /** * 方法執行成功或者異常都會執行*/ public void after(){ System.out.println("最終通知"); } /** * 方法執行之後,執行後置通知,如果程序出現異常,後置通知不會執行*/ public void afterReturn(){ System.out.println("後置通知"); } /** * 方法執行之後,如果程序有異常,才會執行異常通知*/ public void afterThrowing(){ System.out.println("異常通知"); } /** * 環繞通知:方法執行之前和方法執行之後進行通知, * 默認情況下,目標對象的方法不能執行的,需要手動讓目標對象執行*/ public void around(ProceedingJoinPoint joinPoint){ System.out.println("環繞通知1"); //手動讓目標對象的方法執行try { joinPoint.proceed(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("環繞通知2"); }}5)注入實現類和切麵類
<?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"/> <!-- 編寫切麵類配置好--> <bean id="myAspectXml"/> <!-- 配置AOP --> <aop:config> <!-- 配置切麵類:切入點+通知(類型)--> <aop:aspect ref="myAspectXml"> <!-- 配置前置通知,save方法執行之前,增強方法會執行--> <!-- 切入點表達式:execution(public void com.clj.demo5.CustomerDaoImpl.save()) --> <!-- 切入點表達式: 1.execution()固定的,必寫2.public可以省略不寫3.返回值必寫,嚴格根據切入點方法而定,否則增強方法不會執行,可以用*代替,表示任意的返回值4.包名必寫,可以用*代替(如:*..*(默認所有包); com.clj.*) 5.類名必寫,可以部分用*(如*DaoImpl表示以'DaoImpl'結尾的持久層實現類),但不建議用*代替整個類名6.方法必寫,可以部分用*(如save*表示以'save'開頭的方法),但不建議用*代替整個類名7.方法參數根據實際方法而定,可以用'..'表示有0或者多個參數--> <!-- <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)測試
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(); }}擴展:切麵類升級
<?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"/> <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)創建接口和實現類
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表示定義為切麵類*/@Aspectpublic class MyAspectAnno { //通知類型:@Before前置通知(切入點的表達式) @Before(value="execution(public * com.clj.demo1.CustomerDaoImpl.save())") public void log(){ System.out.println("記錄日誌。。"); } //引入切入點@After(value="MyAspectAnno.fun()") public void after(){ System.out.println("執行之後"); } @Around(value="MyAspectAnno.fun()") public void around(ProceedingJoinPoint joinPoint){ System.out.println("環繞通知1"); try { //讓目標對象執行joinPoint.proceed(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("環繞通知2"); } //自定義切入點@Pointcut(value="execution(public * com.clj.demo1.CustomerDaoImpl.save())") public void fun(){ }}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" 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"> <!-- 開啟自動註解代理--> <aop:aspectj-autoproxy/> <!-- 配置目標對象--> <bean id="customerDao"/> <!-- 配置切麵類--> <bean id="myAspectAnno"/></beans>
spring提供了JDBC模板:JdbcTemplate類
1.快速搭建
1)部署環境
這裡在原有的jar包基礎上,還要添加關乎jdbc的jar包,這裡使用的是mysql驅動
2)配置內置連接池,將連接數據庫程序交給框架管理,並配置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"> <!-- 先配置連接池(內置) --> <bean id="dataSource"> <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"> <property name="dataSource" ref="dataSource"/> </bean></beans>
3)測試
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;/** * 測試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); } /** * 測試查詢,通過主鍵來查詢一條記錄*/ @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); }}/** * 定義內部類(手動封裝數據(一行一行封裝數據,用於查詢所有) * @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、配置開源連接池
一般現在企業都是用一些主流的連接池,如c3p0和dbcp
首先配置dbcp
1)導入dbcp依賴jar包
2)編寫配置文件
<!-- 配置DBCP開源連接池--> <bean id="dataSource"> <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>
將模板類中引入的內置類datasource改為開源連接池的
3)編寫測試類
配置c3p0
1)導入c3p0依賴jar包
2)配置c3p0
<!-- 配置C3P0開源連接池--> <bean id="dataSource"> <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>
將模板類中引入的內置類datasource改為開源連接池的
3)編寫測試類
1、什麼是事務
數據庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。 事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向數據的資源。通過將一組相關操作組合為一個要么全部成功要么全部失敗的單元,可以簡化錯誤恢復並使應用程序更加可靠。一個邏輯工作單元要成為事務,必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。事務是數據庫運行中的邏輯工作單位,由DBMS中的事務管理子系統負責事務的處理。
2、怎麼解決事務安全性問題
讀問題解決,設置數據庫隔離級別;寫問題解決可以使用悲觀鎖和樂觀鎖的方式解決
3、快速開發
方式一:調用模板類,將模板注入持久層
1)編寫相對應的持久層和也外層,這裡省略接口
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)配置相對應的配置文件
<?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"> <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"> <property name="dataSource" ref="dataSource"/> </bean><!-- 配置業務層和持久層--> <bean id="accountService"> <property name="accountDao" ref="accountDao"/> </bean><bean id="accountDao"> <!-- 注入模板類--> <property name="jdbcTemplate" ref="jdbcTemplate"/> <property name="dataSource" ref="dataSource"/> </bean></beans>
3)測試類
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(){ //調用支付的方法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"> <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="accountService"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao"> <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,它裡面封轉了模板類,配置文件持久層無需注入模板類,也不需要配置模板類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)更改業務層
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)測試類和上述一樣
4、spring事務管理
Spring為了簡化事務管理的代碼:提供了模板類TransactionTemplate,手動編程的方式來管理事務,只需要使用該模板類即可! !
1、手動編程方式事務(了解原理)
1)快速部署,搭建配置文件,配置事務管理和事務管理模板,並在持久層注入事務管理模板
配置事務管理器
<!-- 配置平台事務管理器--> <bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
配置事務管理模板
<bean id="transactionTemplate"> <property name="transactionManager" ref="transactionManager"/></bean>
將管理模板注入業務層
<bean id="accountService"> <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"> <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="accountService"> <property name="accountDao" ref="accountDao"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean> <bean id="accountDao"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置平台事務管理器--> <bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 手動編碼方式,提供了模板類,使用該類管理事務比較簡單--> <bean id="transactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean></beans>
2)在業務層使用模板事務管理
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; //注入事務模板類private TransactionTemplate transactionTemplate; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } /** * 轉賬的方法*/ public void pay(final String out,final String in, final double money) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { //事務的執行,如果沒有問題,提交,如果楚翔異常,回滾protected void doInTransactionWithoutResult(TransactionStatus arg0) { // TODO Auto-generated method stub accountDao.outMoney(out, money); int a=10/0; accountDao.inMoney(in, money); } }); }}3)測試類和上一致
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(){ //調用支付的方法accountService.pay("佳先森","李釔林",100); }}申明式事務有兩種方式:基於AspectJ的XML方式;基於AspectJ的註解方式
1、XML方式
1)配置配置文件
需要配置平台事務管理
<!-- 配置C3P0開源連接池--> <bean id="dataSource"> <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"> <property name="dataSource" ref="dataSource"/> </bean>
配置事務增強
<tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 給方法設置數據庫屬性(隔離級別,傳播行為) --> <!--propagation事務隔離級別:一般採用默認形式:tx:method可以設置多個--> <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"> <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"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 申明式事務(採用XML文件的方式) --> <!-- 先配置通知--> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 給方法設置數據庫屬性(隔離級別,傳播行為) --> <!--propagation事務隔離級別:一般採用默認形式:tx:method可以設置多個--> <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> <!-- 配置業務層和持久層--> <bean id="accountService"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao"> <property name="dataSource" ref="dataSource"/> </bean></beans>
2)編寫持久層和業務層(省略接口)
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,它裡面封轉了模板類,配置文件持久層無需注入模板類,也不需要配置模板類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)測試類
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(){ //調用支付的方法accountService.pay("佳先森","李釔林",100); }}2、註解方式
1)配置配置文件
配置事務管理
<bean id="dataSource"> <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"> <property name="dataSource" ref="dataSource"/> </bean>
開啟註釋事務
<!-- 開啟事務的註解--> <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"> <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"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 開啟事務的註解--> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 配置業務層和持久層--> <bean id="accountService"> <property name="accountDao" ref="accountDao"/> </bean> <bean id="accountDao"> <property name="dataSource" ref="dataSource"/> </bean></beans>
2)業務層增加@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;//在當前類加此註解表示當前類所有的全部都有事務@Transactionalpublic 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,它裡面封轉了模板類,配置文件持久層無需注入模板類,也不需要配置模板類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)測試類
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(){ //調用支付的方法accountService.pay("佳先森","李釔林",100); }}以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。