SpringAOP的運用方式——注解方式和XML配置方式


SpringAOP的運用方式——注解方式和XML配置方式

AOP(Aspect Oriented Programming):面向切面編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。

主要功能

日志記錄,性能統計,安全控制,事務處理, 異常處理等等。

主要意圖

將日志記錄,性能統計,安全控制,事務處理, 異常處理等代碼從業務邏輯代碼中划分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的代碼。
 
AOP在運用中,大體可以通過兩種處理方式: 注解方式XML配置方式
(一)、注解方式
  a.controller
package controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping
public class ProjectController {
    @RequestMapping("/success/{param}")
    public String goContent(@PathVariable String param, Model model){
        System.out.println(param + "調用了 Controller");
        model.addAttribute("userName",param);
        return "/success";
    }
}
需要通過AOP自動添加日志的controller
  b.切面處理的邏輯
package north;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import java.io.IOException;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "controller")
@Aspect
public class AspectStyleNorth {
    @Pointcut("execution(* controller.*.*(..))")
    public void pointcut() {
        System.out.println("定義切點.....");
    }

    @Before(value="pointcut()")
    public void before() {
        System.out.println("AspectStyleNorth.before()方法執行前執行.....");
    }

    @After("pointcut()")
    public void after(JoinPoint joinPoint) throws IOException {
        System.out.println("AspectStyleNorth.after()方法執行后執行.....");
    }

    @Around(value="pointcut()")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("AspectStyleNorth.around()方法環繞start.....");
        Object rs = new Object();
        try {
            rs = pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("AspectStyleNorth.around()方法環繞end.....");
        return rs;
    }

    @AfterThrowing(value="pointcut()", throwing="e")
    public void exception(Exception e) {
        //記錄異常
        System.out.println("exception ["+e+"]");
    }

}
注解AOP處理的編寫

  c.springmvc.xml中需要配置對 注解類的掃描

<context:component-scan base-package="north"></context:component-scan>

  d.效果

【說明】:around()與before() 開始執行的先后不確定,但before() 必定在around()中 proceedingJoinPoint.proceed()之前執行。

(二)、XML配置方式
  a.controller
package controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping
public class ProjectController {
    @RequestMapping("/success/{param}")
    public String goContent(@PathVariable String param, Model model){
        System.out.println(param + "調用了 Controller");
        model.addAttribute("userName",param);
        return "/success";
    }
}
需要通過AOP自動添加日志的controller
  b.springmvc.xml 的配置,添加運用到注解的類(bean)的掃描
    <!-- 掃描下方切面配置的各個切點所在的包 -->
    <context:component-scan base-package="controller"></context:component-scan>
    
    <!-- 切面配置 -->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* controller.*.*(..))"/>
        <aop:aspect ref="aspectStyleSouth">
            <aop:before pointcut-ref="pointcut" method="before"/>
            <aop:after pointcut-ref="pointcut" method="after"/>
            <aop:around pointcut-ref="pointcut" method="around"/>
            <aop:after-throwing pointcut-ref="pointcut" method="exception" throwing="e"/>
        </aop:aspect>
    </aop:config>

    <bean id="aspectStyleSouth" class="south.AspectStyleSouth"/>

【注】:需要同時掃描兩個地方的包:①AOP附加處理邏輯所在的包;②運用到 AOP 的業務邏輯所在的包。

  c.切面處理的邏輯
package south;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

import java.io.IOException;

@Aspect
public class AspectStyleSouth {

    public void before() {
        System.out.println("before方法執行前執行.....");
    }

    @Pointcut("execution(* server.*.*(..))")
    public void pointcutA() {
        System.out.println("定義切點.....");
    }

    @Before(value="pointcutA()")
    public void beforeA() {
        System.out.println("AspectStyleNorth.before()方法執行前執行.....");
    }


    /**
     *
     * @Title:doAfterInServiceLayer
     * @Description: 方法調用后觸發
     *  記錄結束時間
     * @author shaojian.yu
     * @date 2014年11月2日 下午4:46:21
     * @param joinPoint
     */
    public void after(JoinPoint joinPoint) throws IOException {
        Object[] args = joinPoint.getArgs() == null ? new String[]{""} : joinPoint.getArgs();
        System.out.println("after方法執行后執行....."+args[0]);
    }

    public Object around(ProceedingJoinPoint pjp){
        System.out.println("around方法環繞start.....");
        Object rs = new Object();
        try {
            rs = pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("around方法環繞end.....");
        return rs;
    }

    public void exception(Exception e) {
        //記錄異常
        System.out.println("exception ["+e+"]");
    }
}
XML配置方式中,對於的AOP需要添加的處理邏輯

  d.效果

 

項目的目錄:

 

延伸:

1.在AOP中,需要用到傳參的時,可參考:【第六章】 AOP 之 6.3 基於Schema的AOP ——跟我學spring3

2.AOP中,方法、路徑、參數等匹配的表達式,可參考:Aspectj execution表達式

 


免責聲明!

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



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