spring Aop 註解

来源:http://www.cnblogs.com/jianqiao/archive/2016/11/16/6068559.html
-Advertisement-
Play Games

個人理解: spring Aop 是什麼:面向切麵編程,類似於自定義攔截操作,支持攔截之前操作@Before,攔截之後操作@After,攔截環繞操作@Around。 什麼情況下使用spring Aop:舉例如下 code案例: applicationContext.xml 配置文件 maven po ...


個人理解:

spring Aop 是什麼:面向切麵編程,類似於自定義攔截操作,支持攔截之前操作@Before,攔截之後操作@After,攔截環繞操作@Around。

什麼情況下使用spring Aop:舉例如下

  1. 當需要統計某些方法 or 指定xx開頭的方法名 or 指定xx結尾的方法名 or 某些類下的方法 or 某些包下的方法 or 所有的方法的耗時統計或添加日誌信息時,使用spring Aop 切麵編程可以不用修改任何需要統計或添加日誌的方法,只需很少一部分代碼實現需要做的操作。
  2. 某交易系統需要限制每個登陸用戶查詢次數時,spring Aop 切麵編程在不修改原有代碼上可以完美實現。

code案例:

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" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
           http://www.springframework.org/schema/beans/spring-beans-4.1.xsd   
           http://www.springframework.org/schema/context   
           http://www.springframework.org/schema/context/spring-context-4.1.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-4.1.xsd   
           http://www.springframework.org/schema/task
           http://www.springframework.org/schema/task/spring-task-4.1.xsd ">
	
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
         <property name="locations">
             <value>classpath:propertiesConfig/test.properties</value>
         </property>
    </bean>
	
	<!-- 掃描@Controller註解 -->
	<context:component-scan base-package="com.maven.project">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
	</context:component-scan>
	
	<!-- 開啟AOP監聽 只對當前配置文件有效 -->
	<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
	
	<task:executor id="executor" pool-size="5" />
	<task:scheduler id="scheduler" pool-size="10" />
	<task:annotation-driven executor="executor" scheduler="scheduler" />
	
	<!-- 線程池 -->
	<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">   
		<!-- 線程池維護線程的最少數量 -->
	    <property name="corePoolSize" value="10" />   
	     <!-- 線程池維護線程所允許的空閑時間 -->
	    <property name ="keepAliveSeconds" value ="300" /> 
	    <!-- 線程池維護線程的最大數量 -->
	    <property name="maxPoolSize" value="100" />   
	    <!-- 線程池所使用的緩衝隊列 -->
	    <property name="queueCapacity" value="25" /> 
	</bean>
	
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass">
			<value>org.springframework.web.servlet.view.JstlView</value>
		</property>
		<property name="prefix">
			<value>/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

</beans>

  

maven pom.xml  spring Aop dependency

<!-- Spring AOP + AspectJ  -->
	        <dependency>
	            <groupId>org.springframework</groupId>
	            <artifactId>spring-aop</artifactId>
	            <version>${spring.version}</version>
	        </dependency>
	        <dependency>
	            <groupId>org.springframework</groupId>
	            <artifactId>spring-aspects</artifactId>
	            <version>${spring.version}</version>
	        </dependency>
	        <dependency>
	            <groupId>org.aspectj</groupId>
	            <artifactId>aspectjrt</artifactId>
	            <version>1.6.11</version>
	        </dependency>
	        <dependency>
	            <groupId>org.aspectj</groupId>
	            <artifactId>aspectjweaver</artifactId>
	            <version>1.6.12</version>
	        </dependency>
	        <dependency>
	            <groupId>cglib</groupId>
	            <artifactId>cglib</artifactId>
	            <version>2.2</version>
	        </dependency>
        <!-- end -->

  

spring Aop 切麵業務處理類

package com.maven.project.web.aop;

import org.aspectj.lang.JoinPoint;
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;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class CustomAspect {
    
    //com.maven.project.services包下(包括子包下 的)for開頭的方法
    @Pointcut("execution(* com.maven.project.services..for*(..))")
    public void query(){}
    
    //所有使用@QuerySystem自定義註解的方法 
    @Pointcut("@annotation(com.maven.project.web.customAnnotations.QuerySystem)")
    public void loginTimeOut(){}
    
    
    @Before("query()")//方法之前執行
    public void queryBefore(JoinPoint joinPoint){
        System.out.println("=======query start @Before ====方法名稱:"+joinPoint.getSignature().getName());
    }
    
    @After("query()")//方法之後執行
    public void queryAfter(JoinPoint joinPoint){
        System.out.println("=======query end @After ====方法名稱:"+joinPoint.getSignature().getName());
    }
    
    @Around("query()")//方法前後執行,如果需要返回值,則必須  return joinPoint.proceed(); 返回類型為Object
    public void queryAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("=======query start @Around ====方法名稱:"+joinPoint.getSignature().getName());
        joinPoint.proceed();
        System.out.println("=======query end @Around ====方法名稱:"+joinPoint.getSignature().getName());
    }
    
    @Around("loginTimeOut()")
    public void times(ProceedingJoinPoint joinPoint) throws Throwable{
        long start = System.currentTimeMillis();
        joinPoint.proceed();
        long end = System.currentTimeMillis();
        System.out.println("======= 登陸耗時:"+(end-start)/1000+" ====方法名稱:"+joinPoint.getSignature().getName());
    }
}

 

自定義註解

package com.maven.project.web.customAnnotations;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface QuerySystem {
    String description() default "";
}

 

引用自定義註解的方法

    @RequestMapping("/login")
    @QuerySystem //自定義註解引用
    public void login(HttpServletRequest request, HttpServletResponse response) {
      // 方法實現,,,,
    }

execution 表達式
1、execution(): 表達式主體。
 2、第一個*號:表示返回類型,*號表示所有的類型。
 3、包名:表示需要攔截的包名,後面的兩個句點表示當前包和當前包的所有子包,com.sample.service.impl包、子孫包下所有類的方法。
 4、第二個*號:表示類名,*號表示所有的類。
 5、*(..):最後這個星號表示方法名,*號表示所有的方法,後面括弧裡面表示方法的參數,兩個句點表示任何參數。
 
AspectJ的Execution表達式
execution()是最常用的切點函數,其語法如下所示:
 
execution(<修飾符模式>? <返回類型模式> <方法名模式>(<參數模式>) <異常模式>?)  除了返回類型模式、方法名模式和參數模式外,其它項都是可選的。與其直接講解該方法的使用規則,還不如通過一個個具體的例子進行理解。下麵,我們給出各種使用execution()函數實例。
 
1)通過方法簽名定義切點
 execution(public * *(..))l
匹配所有目標類的public方法,但不匹配SmartSeller和protected void showGoods()方法。第一個*代表返回類型,第二個*代表方法名,而..代表任意入參的方法;
 
 execution(* *To(..))l
匹配目標類所有以To為尾碼的方法。它匹配NaiveWaiter和NaughtyWaiter的greetTo()和serveTo()方法。第一個*代表返回類型,而*To代表任意以To為尾碼的方法;
 
2)通過類定義切點
 execution(* com.baobaotao.Waiter.*(..))l
匹配Waiter介面的所有方法,它匹配NaiveWaiter和NaughtyWaiter類的greetTo()和serveTo()方法。第一個*代表返回任意類型,com.baobaotao.Waiter.*代表Waiter介面中的所有方法;
 
 execution(* com.baobaotao.Waiter+.*(..))l
匹 配Waiter介面及其所有實現類的方法,它不但匹配NaiveWaiter和NaughtyWaiter類的greetTo()和serveTo()這 兩個Waiter介面定義的方法,同時還匹配NaiveWaiter#smile()和NaughtyWaiter#joke()這兩個不在Waiter 介面中定義的方法。
 
3)通過類包定義切點
在類名模式串中,“.*”表示包下的所有類,而“..*”表示包、子孫包下的所有類。
 execution(* com.baobaotao.*(..))l
匹配com.baobaotao包下所有類的所有方法;
 
 execution(* com.baobaotao..*(..))l
匹 配com.baobaotao包、子孫包下所有類的所有方法,如com.baobaotao.dao,com.baobaotao.servier以及 com.baobaotao.dao.user包下的所有類的所有方法都匹配。“..”出現在類名中時,後面必須跟“*”,表示包、子孫包下的所有類;
 
 execution(* com..*.*Dao.find*(..))l
匹配包名首碼為com的任何包下類名尾碼為Dao的方法,方法名必須以find為首碼。如com.baobaotao.UserDao#findByUserId()、com.baobaotao.dao.ForumDao#findById()的方法都匹配切點。
 
4)通過方法入參定義切點
切點表達式中方法入參部分比較複雜,可以使用“*”和“ ..”通配符,其中“*”表示任意類型的參數,而“..”表示任意類型參數且參數個數不限。
 
 execution(* joke(String,int)))l
匹 配joke(String,int)方法,且joke()方法的第一個入參是String,第二個入參是int。它匹配 NaughtyWaiter#joke(String,int)方法。如果方法中的入參類型是java.lang包下的類,可以直接使用類名,否則必須使用全限定類名,如joke(java.util.List,int);
 
 execution(* joke(String,*)))l
匹 配目標類中的joke()方法,該方法第一個入參為String,第二個入參可以是任意類型,如joke(String s1,String s2)和joke(String s1,double d2)都匹配,但joke(String s1,double d2,String s3)則不匹配;
 
 execution(* joke(String,..)))l
匹配目標類中的joke()方法,該方法第 一個入參為String,後面可以有任意個入參且入參類型不限,如joke(String s1)、joke(String s1,String s2)和joke(String s1,double d2,String s3)都匹配。
 
 execution(* joke(Object+)))l
匹 配目標類中的joke()方法,方法擁有一個入參,且入參是Object類型或該類的子類。它匹配joke(String s1)和joke(Client c)。如果我們定義的切點是execution(* joke(Object)),則只匹配joke(Object object)而不匹配joke(String cc)或joke(Client c)。
 

  

 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前端: php後臺接收並查詢: 2.或者: 有$_GET 或者 $_POST ...
  • 1.新的未跟蹤文件 新創建的README文件沒有進行任何跟蹤 $ git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) README no ...
  • Python地鐵的到站流程及原理(個人理解) 今天坐地鐵看著站牌就莫名的想如果用Python寫其工作原理 是不是很簡單就小試牛刀了下大佬們勿噴純屬小弟個人理解 首先來看看地鐵上顯示的站牌如下: 就想這首先站點固定的名稱固定的站點名稱長度可知道,這不是符合列表嘛[第一站,第二站,。。。,最後一站] 把 ...
  • 英文文檔: staticmethod(function) Return a static method for function. A static method does not receive an implicit first argument. The @staticmethod form ...
  • 英文文檔: sorted(iterable[, key][, reverse]) Return a new sorted list from the items in iterable. Has two optional arguments which must be specified as ke ...
  • 變數分為哪些 成員變數:類裡面,方法外面定義的變數 + 實例變數:沒有用static修飾的變數,屬於對象;存在期:創建實例~銷毀實例;作用域:與該實例的生存範圍相同 + 類變數:用static修飾的變數,屬於類;存在期:類的準備階段~銷毀該類;作用域:與類的生存範圍相同 局部變數: + 形參:方法簽 ...
  • ...
  • elasticsearch的config文件夾裡面有兩個配置文件:elasticsearch.yml和logging.yml,第一個是es的基本配置文件,第二個是日誌配置文件,es也是使用log4j來記錄日誌的,所以logging.yml里的設置按普通log4j配置文件來設置就行了。下麵主要講解下e ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...