spring AOP 基於註解(spring版本4.2.0)
阿新 • • 發佈:2019-02-13
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>