Spring之注解實現aop(面向切面編程)


1:Aop(aspect object programming)面向切面編程,名詞解釋:
    1.1:功能:讓關注點代碼與業務邏輯代碼分離
    1.2:關注點
        重復代碼就叫做關注點
    1.3:切面
        關注點形成的類,就叫做切面(類)
        面向切面編程,就是指對很多功能都有的重復代碼抽取,再在運行的時候往業務方法上動態植入"切面類代碼";
    1.4:切入點
        執行目標對象方法,動態植入切面代碼
        可以通過切入點表達式,指定攔截那些類的那些方法,給指定的類在運行的時候植入切面類代碼;
2:注解方式實現aop編程
    2.1:開發步驟
        (1):先引入aop相關的jar文件
            spring-aop-3.2.5.RELEASE.jar【去spring3.2源碼里面找】
            aopalliance.jar【去spring2.5源碼/lib/aopalliance文件里面找】
            aspectjweaver.jar【去spring2.5源碼/lib/aspectj文件里面找】或者【aspectj-1.8.2/lib/aspectjweaver.jar】
            aspectjrt.jar【去spring2.5源碼/lib/aspectj文件里面找】或者【aspectj-1.8.2/lib/aspectjrt.jar】

        《注意:用到的spring2.5版本的jar本艦,如果用jd1.7版本可能會出現問題,
              需要升級以下aspectj組件,即使用aspectj-1.8.2版本中提供的jar文件aspectjweaver.jar和aspectjrt.jar》   

        (2)bean.xml中引入aop名稱空間
      技巧:找到文件spring-framework-3.2.5.RELEASE/docs/spring-framework-reference/htmlsingle
         打開index.html搜索xmlns:aop然后找到下面紅色三句話,分別拷貝到bean.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.xsd

          http://www.springframework.org/schema/aop

          http://www.springframework.org/schema/aop/spring-aop.xsd">

      拷貝之后的bean.xml如下所示:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xmlns:context="http://www.springframework.org/schema/context"
 6     xmlns:aop="http://www.springframework.org/schema/aop"
 7     xsi:schemaLocation="
 8         http://www.springframework.org/schema/beans
 9         http://www.springframework.org/schema/beans/spring-beans.xsd
10         http://www.springframework.org/schema/context
11         http://www.springframework.org/schema/context/spring-context.xsd
12         http://www.springframework.org/schema/aop
13         http://www.springframework.org/schema/aop/spring-aop.xsd">
14 
15 </beans> 

    (3):bean.xml中開啟aop注解掃描,如下配置所示:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xmlns:context="http://www.springframework.org/schema/context"
 6     xmlns:aop="http://www.springframework.org/schema/aop"
 7     xsi:schemaLocation="
 8         http://www.springframework.org/schema/beans
 9         http://www.springframework.org/schema/beans/spring-beans.xsd
10         http://www.springframework.org/schema/context
11         http://www.springframework.org/schema/context/spring-context.xsd
12         http://www.springframework.org/schema/aop
13         http://www.springframework.org/schema/aop/spring-aop.xsd">
14 
15       <!-- 開啟注解掃描 -->
16       <context:component-scan base-package="com.bie.aop"></context:component-scan>   
17         
18       <!-- 開啟aop注解方式,默認為false -->    
19       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
20       
21 </beans>        

     (4):開始寫一個切面類,源碼如下所示:

 1 package com.bie.aop;
 2 
 3 import org.aspectj.lang.annotation.After;
 4 import org.aspectj.lang.annotation.Aspect;
 5 import org.aspectj.lang.annotation.Before;
 6 import org.aspectj.lang.annotation.Pointcut;
 7 import org.springframework.stereotype.Component;
 8 
 9 
10 /** 
11 * @author BieHongLi 
12 * @version 創建時間:2017年3月28日 下午9:10:43 
13 * @Aspect:指定當前類為切面類
14 */
15 @Component  //加入到IoC容器
16 @Aspect  //指定當前類為切面類
17 public class Aop {
18 
19     //指定切入點表達式,攔截那些方法,即為那些類生成代理對象
20     //@Pointcut("execution(* com.bie.aop.UserDao.save(..))")  ..代表所有參數
21     //@Pointcut("execution(* com.bie.aop.UserDao.*())")  指定所有的方法
22     //@Pointcut("execution(* com.bie.aop.UserDao.save())") 指定save方法
23     
24     @Pointcut("execution(* com.bie.aop.UserDao.*(..))")
25     public void pointCut(){
26         
27     }
28     
29     @Before("pointCut()")
30     public void begin(){
31         System.out.println("開啟事務");
32     }
33     
34     @After("pointCut()")
35     public void close(){
36         System.out.println("關閉事務");
37     }
38     
39 }

    (5):寫好切面類就可以寫執行目標對象方法,接口和實現類如下所示:

 1 package com.bie.aop;
 2 
 3 /** 
 4 * @author BieHongLi 
 5 * @version 創建時間:2017年3月28日 下午9:09:29 
 6 * 
 7 */
 8 
 9 public interface IUserDao {
10 
11     public void save();
12 }
 1 package com.bie.aop;
 2 
 3 
 4 import org.springframework.stereotype.Component;
 5 
 6 /** 
 7 * @author BieHongLi 
 8 * @version 創建時間:2017年3月28日 下午9:09:53 
 9 * 目標對象
10 */
11 @Component
12 public class UserDao implements IUserDao{
13     
14     @Override
15     public void save() {
16         System.out.println("..核心業務--核心業務..");
17     }
18 
19     
20 }

    (6):最后就可以進行進行測試了,源碼如下所示:

 1 package com.bie.aop;
 2 
 3 import org.junit.Test;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 /** 
 8 * @author BieHongLi 
 9 * @version 創建時間:2017年3月28日 下午9:13:18 
10 * 
11 */
12 public class AopTest {
13 
14     ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
15     
16     //目標對象有實現接口,spring會自動選擇"jdk代理【動態代理】"
17     //動態代理的標識:class com.sun.proxy.$Proxy10
18     @Test
19     public void test01(){
20         IUserDao dao =  (IUserDao) ac.getBean("userDao");
21         System.out.println(dao.getClass());
22         dao.save();
23     }
24     
25     
26     //class com.bie.aop.OrderDao$$EnhancerByCGLIB$$4952a60a
27     //目標對象沒有實現接口,spring會用"cglib代理哦"
28     @Test
29     public void testCglib(){
30         OrderDao dao =  (OrderDao) ac.getBean("orderDao");
31         System.out.println(dao.getClass());
32         dao.save();
33     }
34 }

  3:心得體會和報錯解決:

    3.1:雖然案例很簡單很簡單,但是我花了三四個小時,為什么呢!我用junit測試spring寫的注解實現aop(面向切面編程)。

    3.2:編輯環境:eclipse+tomcat8.0+jdk1.8,為什么說編輯環境呢,因為jdk1.8和spring好像有仇似的,開始我安裝的jdk是1.8版本的,總之包很多很多錯,主要的caused by:java.lang.IllegalArgumentException【看錯誤主要看caused by】

    3.3:這個錯是UserDao dao =  (UserDao) ac.getBean("userDao");---》

        IUserDao dao =  (IUserDao) ac.getBean("userDao");

        意思就是說必須使用接口來接受從IoC容器獲取的,不能使用實現類接受,不然報的錯夠你喝一壺了

java.lang.ClassCastException: com.sun.proxy.$Proxy10 cannot be cast to com.bie.aop.UserDao
    at com.bie.aop.AopTest.test01(AopTest.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

 

     3.4:然后呢,我就思考就要換成jdk1.7,我去oracle官網搜了,已經沒了jdk1.7,我又去我的百度雲翻出1.7,然后安裝,之后呢,我就驗證唄,其實安裝之前我也思考過,能不能安裝1.8之后再安裝1.7,安裝肯定沒毛病啊,但是總要配置環境變量吧,我就配置jdk1.7之后發現驗證的時候還是顯示是jdk1.8,我就趕緊思考啊,思考過后我考慮應該把jdk1.7,jdk1.8都卸載了,然后我都卸載了,然后重新安裝jdK1.7,之后配置之后,其實主要給Java_home環境變量改一下就行,然后驗證就顯示jdk1.7版本了,之后呢又去測試程序,然而呢,程序之前是jdk1.8,全部報錯了,我又把jdk1.8換成1.7;詳細更換jdk1.8--->jdk1.7的過程如下所示;


首先,第一步:點擊window-->Preferences-->Java-->Installed JREs-->ADD

第二步:點擊add之后顯示如下所示

第三步:點擊next之后點擊如下圖所示的Directory即可;



第四步:點擊項目右擊

第五步:如下所示

第六步:如下所示

第七步:如下所示

第八步:如下所示

第九步:如下所示

然后呢,jdk總算是由jdk1.8換成了1.7,這個過程雖然比較麻煩,但是解決問題,我也很開心啊,加油吧,騷年~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM