1. 程式人生 > >spring AOP 基於註解(spring版本4.2.0)

spring AOP 基於註解(spring版本4.2.0)

spring AOP 概念

spring AOP 如何獲取目標方法的引數,如何在目標方法執行前,修改目標方法的引數。如何在目標方法執行後,修改目標方法的返回結果。

spring AOP 基於註解的實現

需要依賴的jar
aopalliance-1.0.jar,aspectjrt-1.8.7.jar,cglib-nodep-3.2.0.jar,aspectjweaver-1.8.7.jar

被代理類

package com.sky.lp.AAtestAop;

import org.springframework.stereotype.Component;

@Component
public class Human implements Sleepable{ @Override public String sleep(String str) { System.out.println("睡覺了!夢中自有顏如玉!"); return str + "+lp"; // throw new RuntimeException("被代理類拋錯"); } }

被代理類實現的介面

package com.sky.lp.AAtestAop;

public interface Sleepable {

    public
String sleep(String str); }

切面

package com.sky.lp.AAtestAop;

import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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 SleepHelper { //切點 @Pointcut("execution(* com.sky.lp.AAtestAop.Human.*(..))") public void sleeppoint() { } //環繞通知 @Around("sleeppoint()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("進入around通知" + new Date().getTime()); Object object = pjp.proceed();// 執行目標方法 System.out.println("退出around通知" + new Date().getTime()); return object; } //前置通知 @Before("sleeppoint()") public void before() { System.out.println("這裡是Before通知" + new Date().getTime()); } //在連線點正常執行完成後執行,如果連線點丟擲異常,則不會執行 @AfterReturning("sleeppoint()") public void afterReturning() { System.out.println("這裡是afterReturning通知" + new Date().getTime()); } //在連線點丟擲異常後執行,不丟擲異常則不執行 @AfterThrowing("sleeppoint()") public void afterThrowing() { System.out.println("這裡是afterThrowing通知" + new Date().getTime()); } //在連線點執行完成後執行,不管是正常執行完成,還是丟擲異常,都會執行返回通知中的內容 @After("sleeppoint()") public void after() { System.out.println("這裡是After通知" + new Date().getTime()); } }

測試類

package com.sky.lp.AAtestAop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-servlet.xml");
        Sleepable sleeper = (Sleepable)appCtx.getBean("human");
        String str = sleeper.sleep("lp");
        System.out.println("結果:" + str);
    }

}

測試類執行結果
進入around通知1447752935590
這裡是Before通知1447752935590
睡覺了!夢中自有顏如玉!
退出around通知1447752935590
這裡是After通知1447752935590
這裡是afterReturning通知1447752935590
結果:lp+lp

spring-servlet.xml 配置

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
    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/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/util 
      http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <!-- 啟動包掃描功能,以便註冊帶有@Controller、@Service、@repository、@Component等註解的類成為spring的bean -->
    <context:annotation-config />
    <context:component-scan base-package="com.sky.lp.AAtestAop" />

    <!--    <aop:aspectj-autoproxy proxy-target-class="true "/> -->
<!-- proxy-target-class 預設值為 false,設定為 true 意思是 強制使用 CGLIB 動態代理 -->
<!-- 如果不指定 proxy-target-class ,spring會根據 被代理類 是否實現了介面 進行判斷   使用jdk動態代理還是使用CGLIB動態代理。 -->
<!-- 如果 被代理類實現了 介面,則使用JDK動態代理,如果沒有實現介面,則使用CGLIB動態代理。 -->
    <aop:aspectj-autoproxy/>

</beans>