總結切面編程AOP的注解式開發和XML式開發


       有段日子沒有總結東西了,因為最近確實有點忙,一直在忙於hadoop集群的搭建,磕磕碰碰現在勉強算是能呼吸了,因為這都是在自己的PC上,資源確實有點緊張(搭建過程后期奉上),今天難得大家都有空(哈哈哈~~~),給各位總結一下Java開發猿人盡皆知的Spring框架它的核心組件——AOP(面向切面編程)。

       老規矩,首先給各位說說它吧。AOP作為面向切面編程,是一種橫向抽取的思想體現,不錯,有了"橫向切"這個概念呢,我們就應該會聯想到之后的橫切面、切入點,接着你有可能就會閉上眼睛想入非非,但是哥們你千萬不要走歪,咱們現在討論的是Java領域的切面編程,啊哈哈哈~好了,既然是面向切面編程,那么就避免不了"切",都知道,咱們的項目都會從web層到service層到dao層依次執行,既然是切,那么就會從某個層和某個層之間切開,接着就會做一些我們想做的事兒。反正大概的意思就是我所理解的切面編程,譬如切面編程的底層采用動態代理實現,在Spring框架中具體是如何執行的,我就不在這兒啰嗦了,因為這個點兒我也對源碼不是理解的那么透徹,一直在學習的路上,等后期吃到點兒精華再回來給各位完善,下面我就會將我使用2中方式實現AOP切面編程的案例給各位共享一下。

       小小一張圖,請給位笑納:

 

       Spring框架的AOP切面編程分為倆種:注解式開發和XML配置式開發。

項目結構圖:

AOP注解式開發:

       首先我們使用注解式開發,最重要的一點就是能夠讓這些注解生效,何為生效?就是能夠讓它們活着看到spring框架的臨幸,為什么說這個不起眼的問題呢,我在昨天使用注解都開發完了,但是怎么也執行不到切面上的方法,說白了就是注解沒有掃描到,按理論說,切面都是會出現在service層前后,也就是說一般切面會作用在service層上,比如:在更新操作前進行權限校驗、在檢索操作時記錄檢索時長等等。那么我們通常使用spring的容器來掃描這些注解,但是在一些springMVC和spring共存的項目中,我們還不得不注意一下它們父子容器的關系,千萬不要認為父子容器和諧共存,和諧共事【這里打個廣告:有關父子容器的問題,請參考http://www.cnblogs.com/1315925303zxz/p/7211037.html】。我這里掃描切面是由spring容器完成的,因為我的切面類都在service層中了,所以我的切面組件的注解是由父容器spring的配置文件掃描的:

1、開啟AOP注解解析器:

1 <!-- 【啟動AOP的注解解析器】(基於注解方式必須添加該注解解析器)  -->
2 <aop:aspectj-autoproxy/>

2、實現注解切面編程,附:切入點表達式,AOP切入點表達式的書寫格式: 方法返回值 完整包名.類名.方法名(參數)。 注:如果方法返回值和參數類型不限則可以使用*代替,如果以什么什么開頭的方法也可以使用*代替,就如我們配置spring管理事務的傳播行為雷同。涉及到的AOP的通知類型,在第二種XML配置方式中會詳細介紹,哥們兒別停繼續看着。

 1 @Component
 2 @Aspect        //聲明這是一個切面類
 3 public class SelecctAop {
 4     
 5     public static final String REGEX_IP_ADDR = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
 6 
 7     private Date startDate = null;        //專門用於存放開始時間
 8     
 9     /**
10      * 定義一個切入點
11      */
12     @Pointcut("execution(* cn.base.service.*.find*(..))") 13     private void selectPointcut(){}    
14     
15     /**
16      * 檢索開始前的時間記錄
17      * @return
18      * @throws Exception
19      */
20     @Before("selectPointcut()")    //通知類型 21     public void startTime() throws Exception{
22         String hostAddress = InetAddress.getLocalHost().getHostAddress();    //獲取操作用戶的IP地址
23         boolean isLegal = hostAddress.matches(REGEX_IP_ADDR);    //驗證IP地址
24         if(StringUtil.isNullOrBlank(hostAddress) && !isLegal){
25             //如果IP地址為空並且IP地址不合法
26             System.err.println("=============警告:非法用戶操作==============");
27         }
28         startDate = DateTimeUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss");     //開始時間
29         System.err.println(startDate+"【開始】==="+hostAddress+"用戶開始操作");
30     }
31     
32     /**
33      * 檢索結束后的時間記錄、共計操作時長
34      * @throws Exception 
35      */
36     @After("selectPointcut()")    //通知類型 37     public void timeConsuming() throws Exception{
38         String hostAddress = InetAddress.getLocalHost().getHostAddress();    //獲取操作用戶的IP地址
39         boolean isLegal = hostAddress.matches(REGEX_IP_ADDR);    //驗證IP地址
40         if(StringUtil.isNullOrBlank(hostAddress) && !isLegal){
41             //如果IP地址為空並且IP地址不合法
42             System.err.println("=============警告:非法用戶操作==============");
43         }
44         Date endDate = DateTimeUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss");     //結束時間
45         System.err.println(endDate+"【終止】==="+hostAddress+"用戶結束操作");
46         long startTime  = startDate.getTime();
47         long endTime = endDate.getTime();
48         long time = endTime - startTime;
49         System.err.println("================【共計耗時:" + time+ "】=====================");
50     }
51     
52     
53     public static void main(String[] args) {
54 
55     }
56 
57 }

3、只要你訪問調用了service層中檢索操作的方法,就會觸發切面上的方法,我這里是只要用戶進行檢索操作,就會實時記錄該次檢索操作的檢索時長。

 4、效果如圖:

 

XML配置式開發:

       這種方式相對來說比較原始一點兒,就是通過在spring的核心配置文件中進行配置實現AOP切面編程,就是通過將切面類交由spring容器管理,然后通過spring容器的配置將切面類作用與相關業務方法上。

1、更新操作的切面類:

 1 package cn.base.service.aspect;
 2 
 3 import java.net.InetAddress;
 4 import java.net.UnknownHostException;
 5 import com.zxz.utils.DateTimeUtils;
 6 import com.zxz.utils.StringUtil;
 7 
 8 /**
 9  * 更新操作切面類:執行刪除、修改、保存操作時需配置的切面類。[基於XML配置方式實現]
10  * @author zxz
11  */
12 
13 public class UpdateAop {
14     
15     public static final String REGEX_IP_ADDR = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
16     
17     /**
18      * 用戶進行更新操作之前的IP記錄
19      */
20     public void recordIP(){
21         String hostAddress = "";
22         try {
23             hostAddress = InetAddress.getLocalHost().getHostAddress();    //獲取操作用戶的IP地址
24             boolean isLegal = hostAddress.matches(REGEX_IP_ADDR);    //驗證IP地址
25             if(StringUtil.isNullOrBlank(hostAddress) && !isLegal){
26                 //如果IP地址為空並且IP地址不合法
27                 System.err.println("=============警告:非法用戶操作==============");
28             }
29         } catch (UnknownHostException e) {
30             e.printStackTrace();
31         }
32         System.err.println("【==="+DateTimeUtils.getCurrentMsLocal() + "---IP為:" + hostAddress + "進行了更新操作。===】");
33     }
34     
35     public static void main(String[] args) throws Exception {
36 //        String hostAddress = InetAddress.getLocalHost().getHostAddress();
37 //        System.out.println(hostAddress);
38 //        System.out.println(hostAddress.matches(REGEX_IP_ADDR));
39     }
40 
41 }

2、通過spring的配置實現切面編程:

 1 <!-- 配置更新切面類 -->
 2        <bean id="updateAop" class="cn.base.service.aspect.UpdateAop"/> 
 3            
 4        <!-- spring的aop配置(基於XML方式的) -->
 5        <aop:config>
 6            <!-- 配置切入點: 
 7                AOP切入點表達式的書寫格式: 方法返回值 完整包名.類名.方法名(參數)。    注:如果方法返回值和參數類型不限則可以使用*代替。
 8            -->
 9            <aop:pointcut expression="execution(* cn.base.service.*.delete*(..))" id="updatePointcut"/>
10            <!-- 配置切面 -->
11            <aop:aspect ref="updateAop">
12                <!-- 切面的通知類型: 
13                    AOP的通知類型有: 
14                    1、前置通知【before】在方法執行之前進行增強,獲得切入點信息。
15                    2、后置通知【after】在方法執行之后進行增強,獲得方法的返回值。
16                    3、環繞通知【around】在方法執行前后進行增強,[阻止]目標方法執行。
17                    4、異常拋出通知【after-throwing】在方法執行出現異常的時候進行增強,獲得異常信息。
18                    5、最終通知【after-returning】無論方法是否出現異常,最終通知中代碼總是會執行的。
19                 -->
20                <aop:before method="recordIP" pointcut-ref="updatePointcut"/>
21            </aop:aspect>
22        </aop:config>

3、同理,只要你訪問調用了service層中刪除操作時就會觸發切面類上的方法,我這里是當用戶進行刪除操作,則會記錄執行刪除操作的用戶的IP地址並打印在日志中。

 4、效果如圖:

 

 

       [好了,哥們兒到站了,醒醒吧,是不是沒什么技術含量,把你都看醉了,哈哈哈~~~后期會給各位奉上hadoop相關的文章,因為一直在學習的路上,天氣甚好在首都向各位問好!]

 


免責聲明!

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



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