Spring學習4-面向切面(AOP)之aspectj註解方式

1、簡介
  
一、AOP用在哪些方面:AOP可以將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任,例如事務處理、日誌管理、權限控制,異常處理等,封裝起來,便於減小系統的重複代碼,下降模塊間的耦合度,並有利於將來的可操做性和可維護性。
   二、AOP中的概念:
    Aspect(切面):指橫切性關注點的抽象即爲切面,它與類類似,只是二者的關注點不同,類是對物體特徵的抽象,而切面是橫切性關注點的抽象.

  joinpoint(鏈接點):所謂鏈接點是指那些被攔截到的點(能夠是方法、屬性、或者類的初始化時機(能夠是Action層、Service層、dao層))。在spring中,這些點指的是方法,由於spring只支持方法類型的鏈接點,實際上joinpoint還能夠是field或類構造器)

Pointcut(切入點):所謂切入點是指咱們要對那些joinpoint進行攔截的定義,也即
joinpoint的集合.

Advice(通知):
所謂通知是指攔截到joinpoint以後所要作的事情就是通知.通知分爲前置通知,後置通知,異常通知,最終通知,環繞通知

Target(目標對象):代理的目標對象

Weave(織入)
:指將aspects應用到target對象並致使proxy對象建立的過程稱爲織入.

Introduction(引入):
在不修改類代碼的前提下, Introduction能夠在運行期爲類動態地添加一些方法或Field.

   三、AOP帶來的好處::下降模塊的耦合度;使系統容易擴展;更好的代碼複用性


2、經過註解方式實現Spring的AOP
Spring AOP環境的環境與上篇博文spring

Spring接口方式相同

  註解在項目中已經處處都是了,撇開一些優劣不提,開發的便利性和可讀性是很是的方便的。用來配置Spring AOP也很是簡單便利
步驟1、編寫業務類:

@Component    //使用自動註解的方式實例化並初始化該類
public class Business {
   // 切入點
    public String delete(String obj) {
        System.out.println("==========調用切入點:" + obj + "說:你敢刪除我!===========\n");
        return obj + ":瞄~";
    }

    public String add(String obj) {
        System.out.println("================這個方法不能被切。。。============== \n");
        return obj + ":瞄~ 嘿嘿!";
    }

    public String modify(String obj) {
        System.out.println("=================這個也設置加入切吧====================\n");
        return obj + ":瞄改瞄啊!";
    }

}

步驟2、切面類:

 // @Aspect : 標記爲切面類
 // @Pointcut : 指定匹配切點集合
 // @Before : 指定前置通知,value中指定切入點匹配
 // @AfterReturning :後置通知,具備能夠指定返回值
// @AfterThrowing :異常通知
 //注意:前置/後置/異常通知的函數都沒有返回值,只有環繞通知有返回值
@Component    //首先初始化切面類
@Aspect      //聲明爲切面類,底層使用動態代理實現AOP
public class AspectAdvice {

    // 指定切入點匹配表達式,注意它是以方法的形式進行聲明的。
    //即切點集合是:aop.annotation包下全部類全部方法
   //第一個* 表明返回值類型

//若是要設置多個切點可使用 || 拼接
  @Pointcut("execution(* aop.annotation.*.*(..))|| execution(* com.action.admin.*.*update*(..))")
    public void anyMethod() {
    }

    //前置通知
   //在切點方法集合執行前,執行前置通知
   @Before("execution(* aop.annotation.*.*(..))")
    public void doBefore(JoinPoint jp) {
        System.out.println("===========進入before advice============ \n");

        System.out.print("準備在" + jp.getTarget().getClass() + "對象上用");
        System.out.print(jp.getSignature().getName() + "方法進行對 '");
        System.out.print(jp.getArgs()[0] + "'進行刪除!\n\n");

        System.out.println("要進入切入點方法了 \n");
    }

   // 後置通知  
 @AfterReturning(value = "anyMethod()", returning = "result")
    public void doAfter(JoinPoint jp, String result) {
        System.out.println("==========進入after advice=========== \n");
        System.out.println("切入點方法執行完了 \n");

        System.out.print(jp.getArgs()[0] + "在");
        System.out.print(jp.getTarget().getClass() + "對象上被");
        System.out.print(jp.getSignature().getName() + "方法刪除了");
        System.out.print("只留下:" + result + "\n\n");
    }

    // 環繞通知(##環繞通知的方法中必定要有ProceedingJoinPoint 參數,
    //
Filter中的  doFilter方法相似)
   
   @Around("execution(* aop.annotation.*.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("===========進入around環繞方法!=========== \n");
 HttpSession session = ServletActionContext.getRequest().getSession();
     Emp login =(Emp) session.getAttribute("login")
;//ssh2整合後AOP也能夠獲得request、response、session等
        // 調用目標方法以前執行的動做
        System.out.println("調用方法以前: 執行!\n");

        // 調用方法的參數
        Object[] args = pjp.getArgs();
        // 調用的方法名
        String method = pjp.getSignature().getName();
        // 獲取目標對象(形如:com.action.admin.LoginAction@1a2467a)
        Object target = pjp.getTarget();
       //獲取目標對象的類名(形如:com.action.admin.LoginAction)
      String targetName = pjp.getTarget().getClass().getName();
        // 執行完方法的返回值:調用proceed()方法,就會觸發切入點方法執行
        Object result = pjp.proceed();//result的值就是被攔截方法的返回值

        System.out.println("輸出:" + args[0] + ";" + method + ";" + target + ";" + result + "\n");
        System.out.println("調用方法結束:以後執行!\n");
      return result;
    }

    // 異常通知
   
   @AfterThrowing(value = "execution(* aop.annotation.*.*(..))", throwing = "e")
    public void doThrow(JoinPoint jp, Throwable e) {
        System.out.println("刪除出錯啦");
    }

}

 步驟3、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:p="http://www.springframework.org/schema/p"
    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-3.0.xsd    
          http://www.springframework.org/schema/context    
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/aop    
          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    default->

    <context:component-scan base-package="aop.annotation" />
    <!-- 打開aop 註解 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>


</beans>

步驟4、測試類:

public class Debug {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation_aop.xml");
        Business business = (Business) context.getBean("business");
        business.delete("貓");
    }

}
session

相關文章
相關標籤/搜索