第二天 : AOP 面向切面程式設計 、 JdbcTemplete 工具類使用
AOP 面向切面程式設計 、 JdbcTemplete 工具類使用
目錄
3、案例一(不帶切點的切面) : 使用普通Advisor, 使用Advice作為一個切面 ,不定義切點,攔截目標類 所有方法
4) 為目標物件建立 , 配置applicationContext.xml
4 案例二 (帶有切點的切面): 定義單獨切點切面,指定被代理物件 哪些方法 會被增強
2) DefaultAdvisorAutoProxyCreator
1) 下載 匯入 aspectJ 開發包 (AspectJ 依賴 AOP 的 jar包 )
2) 通過jdbcTemplate 提供 int update(String sql, Object... args) 實現增加 、修改 、刪除
一、 什麼是 AOP *****
AOP Aspect Oriented Programing 面向切面程式設計 , 人們說AOP 是對 OOP (面向物件程式設計)思想一個延伸
AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼(效能監視、事務管理、安全檢查、快取)
**** AOP 面向切面程式設計 底層原理 代理!!!
1、 Spring 傳統 AOP
2、 Spring 2.0 之後整合 AspectJ 第三方 AOP技術
相關術語 *****
Joinpoint(連線點):所謂連線點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支援方法型別的連線點.
Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint進行攔截的定義.
Advice(通知/增強):所謂通知是指攔截到Joinpoint之後所要做的事情就是通知.通知分為前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
Introduction(引介):引介是一種特殊的通知在不修改類程式碼的前提下, Introduction可以在執行期為類動態地新增一些方法或Field.
Target(目標物件):代理的目標物件
Weaving(織入):是指把增強應用到目標物件來建立新的代理物件的過程.
spring採用動態代理織入,而AspectJ採用編譯期織入和類裝在期織入
Proxy(代理):一個類被AOP織入增強後,就產生一個結果代理類
Aspect(切面): 是切入點和通知(引介)的結合
二、 AOP 的底層實現
AOP 底層使用的代理技術 : JDK動態代理 和 CGlib的動態代理
1、 JDK動態代理
原理: 針對記憶體中Class物件,使用類載入器 動態為目標物件實現介面的建立代理類
* 代理類 是動態建立的, 代理類 和 被代理物件 實現相同介面
* 被代理物件 必須要實現 介面 (JDK代理 只能針對介面 進行代理 )
public class MyJDKProxy implements InvocationHandler {
private UserDAO userDAO;// 被代理物件
// 通過被代理物件 構造 代理類物件
public MyJDKProxy(UserDAO userDAO) {
this.userDAO = userDAO;
}
/**
* 使用JDK進行 動態代理
*
* @param userDAO
* 被代理物件
* @return
*/
public UserDAO createJDKProxy() {
return (UserDAO) Proxy.newProxyInstance(userDAO.getClass()
.getClassLoader(), userDAO.getClass().getInterfaces(), this);
}
@Override
// 訪問被代理物件 任何方法,都和執行 invoke
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 針對 add 方法進行 增強,記錄日誌 ...
if (method.getName().equals("add")) {// 如果訪問方法 是 add方法
System.out.println("記錄日誌....");
// 呼叫目標方法
return method.invoke(userDAO, args);
} else {
// 其它方法
return method.invoke(userDAO, args);
}
}
}
2、 使用CGlib 完成動態代理
* JDK 動態代理原理, 為目標物件 介面生成代理物件 ,對於不使用介面的業務類,無法使用JDK動態代理
CGLIB(Code Generation Library)是一個開源專案!
是一個強大的,高效能,高質量的Code生成類庫,它可以在執行期擴充套件Java類與實現Java介面。Hibernate支援CGlib 來實現PO位元組碼的動態生成。
* Hibernate 預設PO 位元組碼生成技術 javassist
CGLIB 是一個第三方技術,使用時 ,需要下載 jar 包
http://sourceforge.net/projects/cglib/
* Spring3.2 版本, spring-core jar包 已經整合 cglib 開發類
原理 : CGlib採用非常底層位元組碼技術,可以為一個類建立子類,解決無介面代理問題
public class MyCglibProxy implements MethodInterceptor {
// 目標物件
private ProductDAO productDAO;
// 通過構造器 傳入被代理物件
public MyCglibProxy(ProductDAO productDAO) {
this.productDAO = productDAO;
}
// 建立代理
public ProductDAO createCglibProxy() {
// 建立代理核心物件
Enhancer enhancer = new Enhancer();
// 設定被代理類 (為類建立子類)
enhancer.setSuperclass(productDAO.getClass());
// 設定回撥函式
enhancer.setCallback(this);
// 返回代理 (返回代理子類物件)
return (ProductDAO) enhancer.create();
}
@Override
// 被代理物件所有方法執行 ,都會呼叫 intercept 方法
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
// 為 addProduct 計算運算時間
if (method.getName().equals("addProduct")) {// 當前執行方法
long start = System.currentTimeMillis();
Object result = methodProxy.invokeSuper(proxy, args);
long end = System.currentTimeMillis();
System.out.println("addProduct方法執行時間 : " + (end - start));
return result;
} else {
// 不進行增強
return methodProxy.invokeSuper(proxy, args);
}
}
}
結論:
1).若目標物件實現了若干介面,spring使用JDK的java.lang.reflect.Proxy類代理。
2).若目標物件沒有實現任何介面,spring使用CGLIB庫生成目標物件的子類
程式中應優先對介面建立代理,便於程式解耦維護
三、 Spring AOP
AOP 開發規範 : AOP聯盟為通知Advice定義了org.aopalliance.aop.Interface.Advice
Spring AOP 實現 AOP聯盟定義 規範
1、 傳統Spring AOP 提供 五類 Advice
前置通知(程式碼增強) org.springframework.aop.MethodBeforeAdvice
* 在目標方法執行前實施增強
後置通知 org.springframework.aop.AfterReturningAdvice
* 在目標方法執行後實施增強
環繞通知 org.aopalliance.intercept.MethodInterceptor
* 在目標方法執行前後實施增強
異常丟擲通知 org.springframework.aop.ThrowsAdvice
* 在方法丟擲異常後實施增強
引介通知 org.springframework.aop.IntroductionInterceptor (課程不講 瞭解)
* 在目標類中新增一些新的方法和屬性
2、 Spring 的切面 Advisor
Advisor 就是對PointCut 應用 Advice (通常所說Advisor 指只有一個Point 和 一個 Advice )
型別:
Advisor : 代表一般切面,Advice本身就是一個切面,對目標類所有方法進行攔截 (沒有切點)
PointcutAdvisor : 代表具有切點的切面,可以指定攔截目標類哪些方法
IntroductionAdvisor : 代表引介切面,針對引介通知而使用切面(不要求掌握)
3、案例一(不帶切點的切面) : 使用普通Advisor, 使用Advice作為一個切面 ,不定義切點,攔截目標類 所有方法
1) 匯入jar包
匯入 aop聯盟的規範 : com.springsource.org.aopalliance-1.0.0.jar
匯入 spring aop實現 : spring-aop-3.2.0.RELEASE.jar
2) 編寫被代理 介面和實現類
CustomerDAO
CustomerDAOImpl
3) 編寫前置通知 (在目標方法前執行...)
MyMethodBeforeAdvice
4) 為目標物件建立 , 配置applicationContext.xml
使用ProxyFactoryBean 為目標物件建立代理
<!-- 被代理物件 -->
<bean id="customerDAO" class="cn.itcast.aop.c_advisor.CustomerDAOImpl"></bean>
<!-- 增強 -->
<bean id="mybeforeadvice" class="cn.itcast.aop.c_advisor.MyMethodBeforeAdvice"></bean>
<!-- 建立代理 -->
<bean id="customerDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 目標 -->
<property name="target" ref="customerDAO"></property>
<!-- 針對介面代理 -->
<property name="proxyInterfaces" value="cn.itcast.aop.c_advisor.CustomerDAO"></property>
<!-- 增強
interceptorNames 表示可以運用多個 Advice, 必須寫value
-->
<property name="interceptorNames" value="mybeforeadvice"></property>
</bean>
注意事項: 在程式設計時,應該使用 ProxyFactoryBean 建立後代理物件(CustomerDAOProxy ), 不要引入原來Bean (CustomerDAO)
4 案例二 (帶有切點的切面): 定義單獨切點切面,指定被代理物件 哪些方法 會被增強
* JdkRegexpMethodPointcut 構造正則表示式切點
* 使用正則表示式 切點切面 org.springframework.aop.support.RegexpMethodPointcutAdvisor
1) 建立被代理物件 (沒有介面 的類 )
OrderDAO
2) 增強 (編寫環繞通知)
MyMethodInterceptor
3) 通過配置 ProxyFactory 為目標物件建立代理
<!-- 定義切點切面 -->
<bean id="myadvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 正則表示式規則 -->
<property name="pattern" value=".*"></property>
<property name="advice" ref="mymethodinterceptor"></property>
</bean>
<!-- 建立代理 -->
<bean id="orderDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean" >
<!-- 目標 -->
<property name="target" ref="orderDAO"></property>
<!-- 針對類代理 -->
<property name="proxyTargetClass" value="true"></property>
<!-- 增強 -->
<property name="interceptorNames" value="myadvisor"></property>
</bean>
正則表示式案例
cn\.itcast\.aop\.d_pointcutadvisor\.OrderDAO\.save.* ---- 執行OrderDAO 的save方法
.*save.* ----- 包含save方法
<property name="patterns" value=".*save.*,.*delete.*"></property> ---- 同時增強save和delete方法
5、 自動代理
使用ProxyFactoryBean 建立代理,需要為每個Bean 都配置一次 ,非常麻煩
自動代理原理: 根據xml中配置advisor的規則,得知切面對哪個類的哪個方法進行代理 (切面中本身就包含 被代理物件資訊) ,就不需要ProxyFactoryBean ,使用BeanPostProcessor 完成自動代理
BeanNameAutoProxyCreator 根據Bean名稱建立代理
DefaultAdvisorAutoProxyCreator 根據Advisor本身包含資訊建立代理
* AnnotationAwareAspectJAutoProxyCreator 基於Bean中的AspectJ 註解進行自動代理
1) BeanNameAutoProxyCreator
<!-- 第一種 BeanName自動代理 -->
<!-- 後處理Bean 不需要配置 id -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 對所有DAO結尾Bean 進行代理 -->
<property name="beanNames" value="*DAO"></property>
<!-- 增強 -->
<property name="interceptorNames" value="mymethodinterceptor"></property>
</bean>
*** 自動代理和ProxyFactoryBean 本質區別 :
ProxyFactoryBean, 先有被代理物件, 傳遞ProxyFactoryBean,建立代理
自動代理 , 在Bean構造過程中, 使用後處理Bean 建立代理,返回構造完成物件就是代理物件
2) DefaultAdvisorAutoProxyCreator
基於切面資訊進行代理
<!-- 切面 -->
<bean id="myadvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 切點攔截資訊 -->
<property name="patterns" value="cn\.itcast\.aop\.d_pointcutadvisor\.OrderDAO\.save.*"></property>
<!-- 增強 -->
<property name="advice" ref="mybeforeadvice"></property>
</bean>
<!-- 第二種 基於切面資訊自動代理 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
四、 使用AspectJ 實現AOP *****
AspectJ是一個面向切面的框架,它擴充套件了Java語言。AspectJ定義了AOP語法所以它有一個專門的編譯器用來生成遵守Java位元組編碼規範的Class檔案。
Spring2.0之後 為了簡化 AOP程式設計,支援AspectJ 技術
@AspectJ 是AspectJ1.5新增功能,通過JDK5註解技術,允許直接在Bean類中定義切面
新版本Spring框架,建議使用AspectJ方式來開發AOP ,而不需要使用傳統 Spring AOP 程式設計
1、 基於@AspectJ 程式設計
1) 下載 匯入 aspectJ 開發包 (AspectJ 依賴 AOP 的 jar包 )
AspectJ開發包 com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
匯入spring 整合 aspectj 的jar包 spring-aspects-3.2.0.RELEASE.jar
2) 編寫Spring配置檔案 (需要aop名稱空間)
使用 <aop:aspectj-autoproxy /> 配置自動代理
* 底層 <bean class="... AnnotationAwareAspectJAutoProxyCreator" />
3) @AspectJ 常用註解
@Aspect 定義切面
通知型別
@Before 前置通知,相當於BeforeAdvice
@AfterReturning 後置通知,相當於AfterReturningAdvice
@Around 環繞通知,相當於MethodInterceptor
@AfterThrowing丟擲通知,相當於ThrowAdvice
@After 最終final通知,不管是否異常,該通知都會執行
@DeclareParents 引介通知,相當於IntroductionInterceptor (不要求掌握)
4) 切點表示式定義
切點使用指定哪些連線點 會被增強 , 通過execution函式,可以定義切點的方法切入
語法: execution(<訪問修飾符>?<返回型別><方法名>(<引數>)<異常>)
例如:
execution(public * *(..)) 匹配所有public修飾符 任何方法
execution(* cn.itcast.service.HelloService.*(..)) 匹配HelloService類中所有方法
execution(int cn.itcast.service.UserService.regist(..)) 匹配UserService中int返回型別 regist方法
execution(* cn.itcast.dao..*(..)) 匹配cn.itcast.dao包下 (包含子包) 所有類 所有方法
execution(* cn.itcast.dao.*(..)) 不包含子包
execution(* cn.itcast.dao.GenericDAO+.*(..)) 匹配GenericDAO 所有子類 或者 實現類 所有方法
開發步驟
第一步 : 匯入jar、 自動代理
第二步 : 編寫被代理物件
UserDAO
第三步 : 編寫切面類
@Aspect
// 聲明當前類是一個切面類
public class MyAspect {
// 前置增強
@Before("execution(* cn.itcast.aspectj.a_annotation.UserDAO.*(..))")
public void before1() {
System.out.println("前置增強 1 ...");
}
@Before("execution(* cn.itcast.aspectj.a_annotation.UserDAO.*(..))")
public void before2() {
System.out.println("前置增強2 ...");
}
}
第四步: 配置applicationContext.xml 註冊被代理物件 和 切面類
<!-- 被代理目標 -->
<bean id="userDAO" class="cn.itcast.aspectj.a_annotation.UserDAO"></bean>
<!-- 切面 -->
<bean id="myaspect" class="cn.itcast.aspectj.a_annotation.MyAspect"></bean>
@AspectJ 支援通知型別詳解 :
第一種 前置通知 @Before : 前置通知不能攔截目標方法執行 , 每個前置通知方法接收JoinPoint
* JoinPoint 引包 org.aspectj.lang.JoinPoint
* JoinPoint 獲得攔截增強方法資訊
第二種 後置通知 @AfterReturning : 後置通知,在目標方法執行,返回後 呼叫增強程式碼
* 通過 returning 獲得目標方法返回值
// 後置增強
@AfterReturning(value = "execution(* cn.itcast.aspectj.a_annotation.UserDAO.update(..))", returning = "returnValue")
// returnValue 是代理方法 ,引數名, 用來獲得目標業務方法執行後返回值
public void afterReturning(Object returnValue) {
System.out.println("後置增強.... 獲得方法返回值:" + returnValue);
}
第三種 環繞通知 @Around : 在目標方法前後增強 ,阻止目標方法執行
* 引數為ProceedingJoinPoint 可以呼叫攔截目標方法執行
// 環繞增強
@Around("execution(* cn.itcast.aspectj.a_annotation.UserDAO.search(..))")
// 可以阻止目標方法執行,通過引數
public Object around(ProceedingJoinPoint proceedingJoinPoint)
throws Throwable {
System.out.println("環繞前增強...");
Object result = proceedingJoinPoint.proceed();// 執行目標方法
System.out.println("環繞後增強...");
return result;
}
如果 不寫 proceedingJoinPoint.proceed(); 目標方法就無法執行
第四種 丟擲通知 @AfterThrowing : 在方法出現異常後,該方法獲得執行
* 在方法沒有錯誤時,不會得到執行
// 丟擲增強
@AfterThrowing(value = "execution(* cn.itcast.aspectj.a_annotation.UserDAO.search(..))", throwing = "e")
// throwing 用來指定異常物件 引數名稱
public void afterThrowing(Throwable e) {
System.out.println("不好了,出問題了, " + e.getMessage());
}
第五種 最終通知 @After : 不管目標方法是否存在異常,都將執行 類似finally 程式碼塊(釋放資源)
// 最終增強 ,無論目標方法是否有異常,都必須執行
@After("execution(* cn.itcast.aspectj.a_annotation.UserDAO.search(..))")
public void after() {
System.out.println("這是必須執行的程式碼 .....");
}
@Pointcut 切點定義
在通知上定義切點表示式,會造成一些切點表示式重複
在每個通知內定義切點,會造成工作量大,不易維護,對於重複的切點,可以使用@Poingcut進行定義
格式: private void 無引數方法,方法名為切點名
@Pointcut("execution(* cn.itcast.aspectj.a_annotation.UserDAO.search(..))")
private void mypointcut() {}
應用切點的通知
@After("MyAspect.mypointcut()")
public void after() {
System.out.println("這是必須執行的程式碼 .....");
}
* 在Aspect中 可以定義 多個切點
面試題 : advisor 和 aspect 區別 ?
advisor 是 spring 中 aop定義切面,通常由一個切點和一個通知組成
aspect 是規範中切面 , 允許由多個切點和 多個通知組成
2、 基於XML配置 AspectJ 程式設計
1) 定義被代理物件 ProductDAO
2) 定義切面 MyAspect
3) 編寫Advice增強方法,在xml配置
前置通知
public void before() {
System.out.println("前置增強....");
}
<aop:config>
<!-- 定義切面 -->
<aop:aspect ref="myAspect">
<!-- 切點 -->
<aop:pointcut expression="execution(* cn.itcast.aspectj.b_xml.ProductDAO.*(..))" id="mypointcut"/>
<!-- 通知 -->
<aop:before method="before" pointcut-ref="mypointcut"/>
</aop:aspect>
</aop:config>
後置增強
// 後置增強 (返回值)
public void afterReturing(Object returnVal) {
System.out.println("後置增強,返回值: " + returnVal);
}
<aop:after-returning method="afterReturing" returning="returnVal" pointcut-ref="mypointcut"/>
returning 指定方法代表返回值引數名
環繞增強
public Object around(ProceedingJoinPoint proceedingJoinPoint)
throws Throwable {
System.out.println("環繞前增強...");
Object result = proceedingJoinPoint.proceed();
System.out.println("環繞後增強....");
return result;
}
<aop:around method="around" pointcut-ref="mypointcut"/>
異常通知
public void afterThrowing(Throwable ex) {
System.out.println("發生異常,原因: " + ex.getMessage());
}
<aop:after-throwing method="afterThrowing" throwing="ex" pointcut-ref="mypointcut"/>
最終通知
public void after() {
System.out.println("最終通知....");
}
<aop:after method="after" pointcut-ref="mypointcut"/>
問題:
1、 AOP的思想是什麼 ?
2、 struts2 的攔截器機制使用 AOP的思想? 能說說嗎?
3、 AOP在開發中能實現哪些功能呢?
4、 使用AOP 實現監控業務層方法執行時間? 你會嗎?
五、 Spring JdbcTemplate 使用
1 、 Spring 提供 不同持久化技術 模板工具類
JDBC ---- org.springframework.jdbc.core.JdbcTemplate
Hibernate3.0 --- org.springframework.orm.hibernate3.HibernateTemplate
IBatis(MyBatis) --- org.springframework.orm.ibatis.SqlMapClientTemplate
JPA --- org.springframework.orm.jpa.JpaTemplate
JdbcTemplate 是用來簡化JDBC操作的 , 操作和Apache DbUtils 框架非常類似
2、 快速入門
步驟一 : 匯入jar包
在Spring 最基本jar包 基礎上, 匯入JDBC模板開發包
spring-jdbc-3.2.0.RELEASE.jar --- 存放JdbcTemplate 工具類
spring-tx-3.2.0.RELEASE.jar ---- 進行事務管理
操作資料庫 別忘了驅動
mysql-connector-java-5.1.13-bin.jar ----資料庫連線驅動
步驟二 :編寫配置檔案
1) 建立連線池
2) 構造jdbcTemplate物件
3) 執行SQL語句
步驟二的實現可以分為兩種情況:
*** 情況一:不使用xml 配置資料庫連線池(愚蠢的做法)
程式碼實現:
public void demo1() {
// 1 構造jdbcTemplate 必須 資料庫連線池
// 內建 連線池 DriverManagerDataSource
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring3day2");
dataSource.setUsername("root");
dataSource.setPassword("abc");
// 2、使用連線池構造 jdbcTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// 3、操作資料庫
jdbcTemplate.execute("create table user(id int, name varchar(20))");
}
*** 情況二、使用xml 配置資料庫連線池(明智的選擇)
常用資料來源
* Spring 資料來源實現類 DriverManagerDataSource
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring3day2"></property>
<property name="username" value="root"></property>
<property name="password" value="abc"></property>
</bean>
* DBCP 資料來源 BasicDataSource
匯入jar包
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring3day2"></property>
<property name="username" value="root"></property>
<property name="password" value="abc"></property>
</bean>
* C3P0 資料來源 ComboPooledDataSource (重點掌握)
匯入jar包
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///spring3day2"></property>
<property name="user" value="root"></property>
<property name="password" value="abc"></property>
</bean>
3、 外部屬性檔案引入
在Spring 直接修改常用屬性,不方便,可以將屬性抽取出來 建立單獨 properties 檔案,在Spring 中引入properties
在Spring的applicationContext.xml 引入properties 有兩種寫法
寫法一 :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"></property>
</bean>
將連線池配置引數,使用 ${屬性key}
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
寫法二:
<context:property-placeholder location="classpath:jdbc.properties" />
4、 使用JdbcTemplate 實現CURD 操作
UserDAO 實現資料庫操作,必須要使用 JdbcTemplate, Spring 將jdbcTemplate 注入 UserDAO
1) Spring 為每種持久化技術 提供一個支援類
支援類作用,在DAO 中注入 模板工具類
JDBC : org.springframework.jdbc.core.support.JdbcDaoSupport
Hibernate 3.0 :org.springframework.orm.hibernate3.support.HibernateDaoSupport
iBatis :org.springframework.orm.ibatis.support.SqlMapClientDaoSupport
使用者自己編寫DAO 只需要繼承 JdbcDaoSupport, 就可以注入 JdbcTemplate
2) 通過jdbcTemplate 提供 int update(String sql, Object... args) 實現增加 、修改 、刪除
3) 簡單查詢,返回原始資料型別, String型別
String sql = "select count(*) from user"; // int queryForInt(String sql)
String sql = "select name from user where id = ? "; // <T> T queryForObject(String sql, Class<T> requiredType, Object... args)
4) 複雜查詢
JdbcTemplate 沒有handler, 手動完成物件封裝
編寫實體類 RowMapper
class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
// rs 已經指向每一條資料,不需要自己呼叫 next,將rs指向資料 轉換 User物件
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
return user;
}
}
查詢單個物件 <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args)
return this.getJdbcTemplate().queryForObject(sql, new UserRowMapper(),id);
//RowMapper:行對映器---把每一條記錄轉換成一個物件
查詢所有物件List集合 <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args)
return this.getJdbcTemplate().query(sql, new UserRowMapper());
總結:
1、 AOP概述 : 橫向抽取機制和縱向繼承 , AOP術語 (掌握)
2、 AOP 底層實現 : JDK動態代理 和 CGLib 動態代理 (瞭解)
3、 使用ProxyFactoryBean 建立代理 (瞭解)
無切點切面
帶有切點切面
4、 掌握自動代理如何實現 ---- 後處理Bean ,在Bean構造過程中完成代理
5、 註解 實現 AspectJ (掌握)
@Aspect
@Pointcut
@Before @AfterReturning @Around @AfterThrowing @After 必須
**** 重點使用 @Around 環繞增強 (日誌、執行時間、許可權)
6、 XML 實現AspectJ (掌握)
7、 JdbcTemplate (掌握)
資料庫連線池配置
外部屬性檔案
增刪改查DAO