日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringAOP描述及实现_AspectJ详解_基于注解的AOP实现_SpringJdbcTemplate详解

發布時間:2024/7/5 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringAOP描述及实现_AspectJ详解_基于注解的AOP实现_SpringJdbcTemplate详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

AOP

AOP特點:

  • 面向切面編程, 利用AOP對業務邏輯的各個部分進行抽取公共代碼, 降低耦合度, 提高代碼重用性, 同時提高開發效率.
  • 采取橫向抽取, 取代傳統縱向繼承體系重復性代碼
  • 解決事務管理, 性能監視, 安全檢查, 緩存, 日志等問題
  • Spring AOP在運行期, 通過反向代理的方式解決類加載, 屬性注入
  • AspectJ是基于Java的AOP框架, 在Spring使用AspectJ實現AOP

AOP實現機制:
底層采用代理機制實現AOP.
2 種代理機制: 1.采用JDK的的動態代理Proxy; 2.采用CGLIB字節碼增強

AOP專業術語:
Target: 目標類 ( 需要被代理的類 )
Joinpoint: 連接點 ( 可能需要使用的目標類方法 )
Advice: 增強代碼 ( 對連接點增強的代碼 )
PointCut: 切入點 ( 可能需要 Advice 增強的連接點 )
Weaving: 織入 ( 創建代理對象 proxy 執行切入點的方法 )
Aspect: 切面 ( Advice 與 PointCust的結合 )

JDK/CGLIB的AOP實現

下面通過JDK動態代理和CGLIB字節碼增強兩種方式實現AOP操作
當目標類沒有實現接口或者需要更好的性能的時候就需要考慮使用CGLIB實現動態Proxy

JDK動態代理:
1.目標類: Service層
2.切面類: 使用JDK動態代理對Service層代碼增強
3.工廠類: 獲得proxy對象

//目標類 public interface UserService {void addUser();void updateUser();void deleteUser(); } public class UserServiceImpl implements UserService {public void addUser() {System.out.println("add User");}public void updateUser() {System.out.println("update User");}public void deleteUser() {System.out.println("delete User");} }切面, 增強連接點: public class MyAspect {public void before(){System.out.println("before");}public void after(){System.out.println("after");} }靜態代理對象工廠: public class MyProxyBeanFactory {public static UserService createService(){final UserService userService = new UserServiceImpl();final MyAspect myAspect = new MyAspect();//通過userService獲得代理對象UserService proxyService = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new InvocationHandler(){//Proxy代理對象, method代理類的目標方法, args目標方法參數public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {//織入橫向代碼myAspect.before();//執行代理類的方法Object obj = method.invoke(userService, args);myAspect.after();//返回執行代理方法的返回值return obj;}});//返回代理對象return proxyService;} }applicationContext.xml: <bean id="userService" class="com.f_aop.jdkproxy.MyProxyBeanFactory" factory-method="createService"></bean>測試方法:@Testpublic void f1(){String XMLPATH="com/f_aop/jdkproxy/applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(XMLPATH);UserService userService = (UserService) applicationContext.getBean("userService");userService.addUser();userService.updateUser();userService.deleteUser();}

CGLIB字節碼增強動態代理:
原理: cglib動態生成一個代理類的子類, 子類重寫代理類的所有不是final的方法, 在子類中采用方法攔截技術攔截所有父類的方法調用, 順勢織入切面邏輯, 實現AOP, 它比JDK動態代理要快.
其操作流程與JDK動態代理一致.
下面只給出靜態代理工廠的代碼:

public class MyProxyBeanFactory {public static UserService createService(){final UserService userService = new UserServiceImpl();final MyAspect myAspect = new MyAspect();//創建代理Enhancer enhancer = new Enhancer();//確定父類enhancer.setSuperclass(userService.getClass());//向代理對象的方法中織入切面代碼enhancer.setCallback(new MethodInterceptor() {public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {myAspect.before();//執行目標方法//Object obj = method.invoke(userService, args);//執行目標方法, 效果與method.invoke(userService, args);//一般執行這個方法, 速度要快一些Object obj = methodProxy.invoke(proxy, args);myAspect.after();//返回目標方法返回值return obj;}});//使用enhancer創建代理對象return (UserService) enhancer.create();} }

cglib的整個流程與JDK的動態代理都是一樣的, 就在底層處理接口和加載字節碼文件有區別

AOP聯盟通知類型

AOP聯盟定義Advice規范, 編寫Advice代碼需實現Advice接口.
Spring按照Advice在目標類中方法的連接點的位置, 分為5類

前置通知: 實現接口: org.springframework.aop.MethodBeforeAdvice只在目標方法前進行代碼增強; 后置通知: 實現接口: org.springframework.aop.AfterReturningAdvice只在目標方法后進行代碼增強; 環繞通知( 必須手動執行目標方法 ): 實現接口: org.springframework.aop.MethodInterceptor只在目標方法前后進行代碼增強; 效果等同于JDK的Proxy/cglib 異常通知: 實現接口: org.springframework.aop.ThrowsAdvice在拋出異常的時候進行代碼增強; 引介通知:實現接口: org.springframework.aop.IntroductionInterceptor只在目標類中增添一些新的方法和屬性;

AOP聯盟的代理實現

  • 使用Spring提供的ProxyFactoryBean模擬代理過程, 實現Spring的AOP:

使用環繞型通知進行演示(目標類與前面的一樣):

1.導入aop, aopalliance jar包 2.切面類(MyAspect)實現MethodInterceptor接口 3.實現MethodInterceptor中invoke方法, 手動織入橫向代碼 4.在applicationContext.xml中配置, 使用Spring提供的ProxyFactoryBean對目標類實現代理

演示代碼:

切面類: public class MyAspect implements MethodInterceptor{@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {System.out.println("前");//手動執行目標方法Object obj = mi.proceed();System.out.println("后");//返回目標方法執行的返回值return obj;} }配置applicationContext.xml:<!-- 獲得目標類對象 --><bean id="userService" class="com.f_aop.methodInterceptor.UserServiceImpl"></bean><!-- 創建切面類 --><bean id="myAspect" class="com.f_aop.methodInterceptor.MyAspect"></bean><!-- 創建代理類, 使用Spring配備的代理工廠 --><bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean"><!-- 指定接口 --><property name="interfaces" value="com.f_aop.methodInterceptor.UserService"></property><!-- 確定目標類對象 --><property name="target" ref="userService"></property> <!-- 確定Aspect, 由于interceptorNames的形參值是String[], 所以使用value, 而非ref --><property name="interceptorNames" value="myAspect"></property><property name="optimize" value="true"></property></bean>測試方法:@Testpublic void f1(){String XMLPATH="com/f_aop/methodInterceptor/applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(XMLPATH);//使用proxyService, 而非userService//通過代理對象執行AdviceUserService userService = (UserService) applicationContext.getBean("proxyService");userService.addUser();userService.updateUser();userService.deleteUser();}運行結果: 前 add User 后 前 update User 后 前 delete User 后

applicationContext.xml中創建代理類標簽詳解

ProxyFactoryBean: Spring的代理工廠,生成代理對象interfaces: 目標類實現的接口, 多個值使用<array><value>確定每個值單個值的時候直接使用valuetarget: 確定目標類interceptorNames: 確定切面類的名稱, 類型為String[], 使用value, 切記不使用refoptimize: 強制底層使用cglib當沒有設置optimize的值時:Spring自動判斷, 沒有接口使用cglib, 有接口使用jdk顯式設置optimize, 如果聲明optimize=true,無論是否有接口,都采用cglib

上面這種代理實現, 是在applicationContext.xml配置文件中模擬代理工廠產生代理對象, 在測試函數中獲得是容器產生的代理對象proxyService.

  • 利用AspectJ簡化Spring中ProxyFactoryBean的配置:
    使用環繞型通知進行演示, 編寫流程:
1.導入aspectj.weaver jar包. 2.在applicationContext.xml配置文件中添加aop的xmlns和xsi限制 3.在配置文件中配置切面類(MyAspect)的切入點(PointCut), 特殊切面(包含advice與PointCut).首先使用expression表達式配置切入點(PointCut), 即目標類中哪些方法需要增強.然后配置特殊切面, 對配置好的切入點, 使用增強點advice進行增強.

下面使用代碼演示, 因為只需修改配置文件與測試類, 只給出配置文件代碼:

<?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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="userService" class="com.f_aop.aspectJ.UserServiceImpl"></bean><!-- 創建切面類 --><bean id="myAspect" class="com.f_aop.aspectJ.MyAspect"></bean><!-- 配置特殊切面 --><!-- proxy-target-class配置是否使用cglib --><aop:config proxy-target-class="true"><aop:pointcut id="myPointCut" expression="execution(* com.f_aop.aspectJ.*.*(..))"/><aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/></aop:config> </beans><!--aop:config: 配置AOPproxy-target-class: 配置是否強行使用cglib, 效果與前面的optimize一樣pointcut: 配置切入點.expression: 配置切入點表達式,用于獲得目標類中需要增強的目標方法.advisor: 配置切入點與切面類, 指明哪些方法需要增強.advice-ref: 切入類對象引用.pointcut-ref: 切入點引用. -->

相比于Spring提供的ProxyFactoryBean, AspectJ更加便捷.

AspectJ詳解

AspectJ是基于Java的AOP框架, 用于自定義AOP開發.

  • 切入點表達式
    用于描述目標類中的目標方法, 指定哪些方法可作為切入點.
    下面說明切入點表達式寫法:
語法: expression = " execution( 修飾符 返回值 包.類.方法名(參數) throws 異常 ) "切入表達式針對每個部分的編寫規則如下 修飾符(一般省略):public 公共方法* 任意方法 返回值(不能省略):void 沒有返回值String 返回值為字符串* 返回值任意 包(可省略):com.demo 固定包com.demo.* demo下任意子包,例如:com.demo.aopcom.demo.. demo下所有包(包含自己,也包含多級子包)com.demo.*.service.. demo下任意子包, 子包中包含固定包service,service下所有包 類(可省略):UserServiceImpl 指定類*Impl 以Impl結尾的類User* 以User開頭的類* 任意類 方法名(不能省略):addUser 指定方法add* 以add開頭的方法*User 以User結尾的方法* 任意方法 參數:() 無參(int) 一個int型參數(int, int) 兩個int型參數(..) 任意參數 throws(可省略, 一般不寫)下面給出一個例子: 1.execution(* com.demo.*.service..*.*(..))指定com.demo下具有固定service包的任意子包中任意類中的任意方法,方法返回值任意.其他種類的expression表達式: 1.within: 匹配包或子包中的方法.within(com.demo..*) demo下所有包中任意類中任意方法 2.this: 匹配實現接口的類的代理對象中方法:this(com.demo.aop.user.UserDAO) 匹配UserDAO中實現類代理對象任意方法. 3.target: 匹配實現接口的類的目標對象中方法:target(com.demo.aop.user.UserDAO) 匹配UserDAO中實現類目標對象任意方法. 4.args: 匹配參數格式符合標準的方法args(int, int) 匹配形參值類型為int, int的任意方法. 5.bean(id): 匹配指定bean所有方法bean('userService') 匹配userService中所有方法
  • AspectJ通知類型
    與AOP聯盟一樣, AspectJ也定義了多種通知類型.

AspectJ總共6中通知類型:

1.before: 前置通知,用于校驗數據在目標方法之前執行, 若拋出異常, 組織目標方法運行. 2.afterReturning: 后置通知,常規數據處理目標方法執行后執行, 可獲得目標方法的返回值.目標方法出現異常, 方法不執行. 3.around: 環繞通知目標方法前后, 可阻止目標方法執行, 必須手動執行目標方法. 4.afterThrowing: 拋出異常通知目標方法出現異常后執行, 沒有出現異常就不執行. 5.after: 最終通知, 資源回收, 類似finally方法方法執行完, 無論方法中是否出現異常, 都將執行.環繞通知與其他通知之間的聯系: try{//前置: before//手動執行目標方法//后置: afterReturning } catch(){//捕獲異常: afterThrowing } finally{//最終通知: after }

從上面看出, 完全可以使用環繞通知模擬前置通知, 后置通知, 環繞通知結合AfterThrowing, After實現AOP.

aop標簽對應的通知類型種類

使用AOP聯盟進行切面類編寫, 需要定義通知類型, 切面類必須實現特定接口(MethodInterceptor), 然后為目標方法添加增強代碼, 相比于AOP聯盟, AspectJ只要定義切面類, 增強代碼的使用完全交給配置文件, 避免代碼污染, 簡化操作.

使用AspectJ實現SpringAOP

基于xml配置通知類型的開發流程:
1.導入AOP聯盟, AspectJ, AOP依賴, Aspect規范 jar包.
2.編寫目標類: 接口與實現類.
3.編寫切面類: 編寫AspectJ的通知類型方法, 方法名任意, 無需實現什么接口.
4.配置xml: 配置通知類型.
5.測試.

下面給出演示代碼, 代碼中已經給出注釋加以說明(若有不懂請在評論區留言):

目標類 ( 接口與實現類 ): public interface UserService {void addUser();void updateUser();void deleteUser(); } public class UserServiceImpl implements UserService {public void addUser() {System.out.println("add User");}public void updateUser() {System.out.println("update User");}public void deleteUser() {System.out.println("delete User");} }切面類: package com.f_aop.aspectJFinal;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint;public class MyAspect{// 測試前置通知與后置通知 // public void myBefore(JoinPoint jPoint){ // System.out.println("前置通知"+jPoint.getSignature().getName()); // } // // public void myAfterReturning(JoinPoint jPoint, Object ret){ // System.out.println("后置通知"+jPoint.getSignature().getName()+"--"+ret); // }public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前置通知");//手動執行目標方法Object obj = joinPoint.proceed(); // 環繞通知與拋出異常通知的測試結果: // int i = 1/0; // 前置通知 // add User // 拋出異常通知/ by zero // 最終通知System.out.println("后置通知");return obj;}public void myAfterThrowing(JoinPoint jPoint, Throwable e){System.out.println("拋出異常通知"+e.getMessage());}public void myAfter(JoinPoint jPoint){System.out.println("最終通知");} }applicationContext.xml: <?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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 創建目標類對象 --><bean id="userService" class="com.f_aop.aspectJFinal.UserServiceImpl"></bean><!-- 創建切面類 --><bean id="myAspect" class="com.f_aop.aspectJFinal.MyAspect"></bean><!-- 使用 config 配置AspectJ的AOP --><aop:config><!-- 聲明切入面 --><aop:aspect ref="myAspect"><!-- 配置目標方法的切入點 --><aop:pointcut id="myPointCut" expression="execution(* com.f_aop.aspectJFinal.UserServiceImpl.*(..))"/><!-- 配置通知類型的時候, method代表切入類方法, pointcut-ref代表目標類切入點.二者結合的意思就是目標類中哪些切入點需要切入方法進行增強.--><!-- 前置通知 <aop:before method="myBefore" pointcut-ref="myPointCut"/>后置通知, returning用于接收目標方法執行完后的返回值<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret"/>--><!-- 拋出異常通知要配合環繞通知使用, 環繞通知拋出的異常使用拋出異常通知接收 --><aop:around method="myAround" pointcut-ref="myPointCut"/><!-- 拋出異常, throwing="e" 代表執行目標方法后,可能會拋出的異常通過 e 進行接收 --><aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/><!-- 最終通知 --><aop:after method="myAfter" pointcut-ref="myPointCut"/></aop:aspect></aop:config> </beans>測試方法:@Testpublic void f1(){String XMLPATH="com/f_aop/aspectJFinal/applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(XMLPATH);UserService userService = (UserService) applicationContext.getBean("userService");//測試AOPuserService.addUser();userService.updateUser();userService.deleteUser();}

基于注解的通知類型開發流程:
1.在剛開始配置注解的時候, 可以按照 xml 中bean, aop的配置信息來給類/屬性添加注解, 這樣不容易把邏輯搞混.
2.測試, 其實整個開發過程與 xml 配置沒什么區別, 都是一樣的, 只是形式上有區別.

在給各種類添加注解之間, 一定要牢記:

1.在 xml 配置文件中添加掃描, 掃描注解類:<context:component-scan base-package="com.demo.aspectJAnnotation"></context:component-scan> 2.確定AOP注解生效:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

AspectJ中通知類型的注解種類:

1.@Aspect 聲明切面類, 不需要指定切面類名稱.等同于<aop:aspect ref="myAspect">, 一般與 @Component 結合使用, Component代表myAspect對象2.@Pointcut("execution(* com.f_aop.aspectJFinalAnnotation.UserServiceImpl.*(..))")聲明公共切入點, 通過"方法名"獲得切入點引用.等同于<aop:pointcut id="myPointCut" expression="execution(* com.f_aop.aspectJFinalAnnotation.UserServiceImpl.*(..))"/>2.@Before(value="execution(* com.demo..service.*.*(..))")前置通知, 直接添加在切面類方法前.等同于<aop:before method="myBefore" pointcut-ref="myPointCut"/>或者上面 @Before 也可寫做 @Before(value="myPointCut()") myPointCut是方法名此時要先在切面類中聲明公共切入點方法: @Pointcut("execution(* com.f_aop.aspectJFinalAnnotation.UserServiceImpl.*(..))")private void myPointCut(){}這樣寫的作用就是為了少寫代碼, 避免在多個切面類通知方法前都要加execution=(...).并且如果切入點表達式寫錯了, 也很難排查問題.(不懂請看下面的演示代碼)3.@AfterReturning(value="myPointCut()", returning="ret")后置通知, 直接添加在后置通知方法前.等同于<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret"/>ret表示接收的返回值名稱, 含有與標簽中的ret一樣.4.@Around("myPointCut()")環繞通知, 添加在環繞方法前面.等同于<aop:around method="myAround" pointcut-ref="myPointCut"/>5.@AfterThrowing(value="myPointCut()", throwing="e")拋出異常通知, 添加在拋出異常通知方法前.等同于<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>6.@After("myPointCut()")最終通知, 添加在最終通知之前.等同于<aop:after method="myAfter" pointcut-ref="myPointCut"/>

接下來給出演示代碼:

目標類: package com.f_aop.aspectJFinalAnnotation; import org.springframework.stereotype.Service;//生成UserService的bean: userService @Service("userService") public class UserServiceImpl implements UserService {public void addUser() {System.out.println("add User");}public void updateUser() {System.out.println("update User");}public void deleteUser() {System.out.println("delete User");} }xml 配置文件 applicationContext.xml: <?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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 掃描注解類 --><context:component-scan base-package="com.f_aop.aspectJFinalAnnotation"></context:component-scan><!-- 確定AOP注解生效 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>切面類: package com.f_aop.aspectJFinalAnnotation;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component;//獲得切面類Bean @Component //聲明切面類 @Aspect //由于二者都修飾同一個類, 所以不加idpublic class MyAspect{//直接設置切入點, 不使用自定義的公共切入點 // @Before("execution(* com.f_aop.aspectJFinalAnnotation.UserServiceImpl.*(..))") // public void myBefore(JoinPoint jPoint){ // System.out.println("前置通知"+jPoint.getSignature().getName()); // }// 設置切入點, 通過returning獲得返回值 // @AfterReturning(value="myPointCut()", returning="ret) // public void myAfterReturning(JoinPoint jPoint, Object ret){ // System.out.println("后置通知"+jPoint.getSignature().getName()+"--"+ret); // }@Pointcut("execution(* com.f_aop.aspectJFinalAnnotation.UserServiceImpl.*(..))")private void myPointCut(){//配置空方法,用于聲明公共切入點}@Around("myPointCut()")public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前置通知");//手動執行目標方法Object obj = joinPoint.proceed();int i = 1/0; // 前置通知 // add User // 拋出異常通知/ by zero // 最終通知System.out.println("后置通知");return obj;}@AfterThrowing(value="myPointCut()", throwing="e")public void myAfterThrowing(JoinPoint jPoint, Throwable e){System.out.println("拋出異常通知"+e.getMessage());}@After("myPointCut()")public void myAfter(JoinPoint jPoint){System.out.println("最終通知");}}

JdbcTemplate

主要是Spring提供操作Jdbc的工具類, 類似于DBUtils, 依賴于連接池DataSource.

開發流程:
1.創建數據庫表.
2.導入 C3P0/DBCP連接池, mysql驅動, Spring-jdbc, spring-tx, 等Spring其余核心jar包
3.創建JavaBean, 配置數據源
4.編寫DAO層
5.配置applicationContext.xml文件, 使用Spring管理DAO層對象
6.測試.

下面使用C3P0進行測試, DBCP與C3P0是一樣的, 只是在配置數據庫連接上有所不同.

數據庫:create table t_user(id int primary key,name varchar(10);password varchar(10) );User: public class User implements Serializable{private Integer id;private String name;private String password;//構造方法, get/set方法 }UserDao: public class UserDao{//使用Spring提供的JdbcTemplate, 在Spring配置文件中注入private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}//查詢所有的Userpublic List<User> findAll(){return jdbcTemplate.query("select * from t_user", ParameterizedBeanPropertyRowMapper.newInstance(User.class));}//演示查詢單個Userpublic void find(User user){String sql = "select * from t_user"; // String sql = "select * from t_user where id=?"; // Object findUserId = user.getId();//查詢條件信息就加Object參數 // List<Map<String,Object>> queryForList = jdbcTemplate.queryForList(sql, findUserId);//查詢所有直接不加參數List<Map<String, Object>> queryForList = jdbcTemplate.queryForList(sql);for (Map<String, Object> map : queryForList) {//一個map中儲存著一個學生的信息for (Map.Entry<String, Object> m : map.entrySet()) {System.out.println(m.getKey()+"--"+m.getValue());}}//匿名內部類, 實現RowMapper接口, 自定義查詢結果類型/*List<User> queryUsers = jdbcTemplate.query(sql, new RowMapper<User>(){@Overridepublic User mapRow(ResultSet resultSet, int i) throws SQLException {return new User(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("password"));}});同理帶條件查詢, jdbcTemplate.query(sql, rowMapper, i)*/} // @Testpublic void insert(User user){String sql = "insert into t_user(id, name, password)values(?, ?, ?)";//Object數組中參數對應sql中"?"的順序Object[] obj = new Object[]{user.getId(), user.getName(), user.getPassword()};//受影響行數int row = jdbcTemplate.update(sql, obj);System.out.println("受影響行數"+row);}public void update(User user){String sql = "update t_user set name=? where id=?";Object[] obj = new Object[]{user.getName(), user.getId()};//受影響行數int row = jdbcTemplate.update(sql, obj);System.out.println("受影響行數"+row);}public void delete(User user){String sql = "delete from t_user where id=?";Object[] obj = new Object[]{user.getId()};//受影響行數int row = jdbcTemplate.update(sql, obj);System.out.println("受影響行數"+row);} }applicationContext.xml配置文件: <?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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 創建數據源Bean --><bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property><property name="user" value="root"></property><property name="password" value="12345"></property></bean><!-- 創建模板Bean, 向JdbcTemplate中注入數據源 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="comboPooledDataSource"></property></bean><!-- 配置DAO, 向Dao注入JdbcTemplate Bean --><bean id="userDao" class="com.g_jdbc.c3p0.UserDao"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean></beans>測試方法: @Testpublic void f1(){String xml = "com/g_jdbc/c3p0/applicationContext.xml";ApplicationContext application = new ClassPathXmlApplicationContext(xml);UserDao bean = (UserDao) application.getBean("userDao");//查詢List<User> list = bean.findAll();for (User user : list) {System.out.println(user);}}

這里給出DBCP的配置文件寫法, 用于區別C3P0:
二者只有創建數據源有所不同

<!-- 創建數據源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/test"></property><property name="username" value="root"></property><property name="password" value="12345"></property></bean>

使用JdbcTemplate還有這種簡化寫法:
Spring提供JdbcDaoSupport, 用于封裝JdbcTemplate, 使得DAO不用關心JdbcTemplate模板的處理.

1.讓Dao繼承JdbcDaoSupport, 創建模板的過程交給父類處理.

public class UserDao extends JdbcDaoSupport{//使用JdbcDaoSupport通過get方法獲得數據源,JdbcTemplate模板public List<User> findAll(){String sql = "select * from t_user";//使用getJdbcTemplate()獲取父類創建好的模板, 然后再執行查詢操作return this.getJdbcTemplate().query(sql, ParameterizedBeanPropertyRowMapper.newInstance(User.class));}}

2.修改配置文件.

<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property><property name="user" value="root"></property><property name="password" value="12345"></property></bean><!-- 配置DAO使用JdbcDaoSupport, 底層已經封裝了JdbcTemplate, 只需配置DataSource即可--><bean id="userDao" class="com.g_jdbc.jdbcdaosupport.UserDao"><property name="dataSource" ref="comboPooledDataSource"></property></bean>

3.測試:

//測試方法和C3P0, DBCP的測試方法是一樣的 @Testpublic void f1(){String xml = "com/g_jdbc/jdbcdaosupport/applicationContext.xml";ApplicationContext application = new ClassPathXmlApplicationContext(xml);UserDao bean = (UserDao) application.getBean("userDao");List<User> list = bean.findAll();for (User user : list) {System.out.println(user);}}

總結

以上是生活随笔為你收集整理的SpringAOP描述及实现_AspectJ详解_基于注解的AOP实现_SpringJdbcTemplate详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。