Spring4學習筆記-AOP(基於註解的方式)
1.加入jar包
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
spring-aop-4.1.0.RELEASE.jar
spring-aspects-4.1.0.RELEASE.jar
spring-beans-4.1.0.RELEASE.jar
spring-context-4.1.0.RELEASE.jar
spring-core-4.1.0.RELEASE.jar
spring-expression-4.1.0.RELEASE.jar
2.在配置檔案中加入AOP的名稱空間
3.基於註解的方式
①在配置檔案中加入如下配置
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②把橫切關注點的程式碼抽象到切面的類中
切面首先是一個IOC中的bean,即加入@Component註解
切面還需要加入@Aspect註解
③在類中宣告各種通知
@Before 前置通知,在方法執行之前執行
@After 後置通知,在方法執行之後執行
@AfterRunning 返回通知,在方法返回結果之後執行
@AfterThrowing 異常通知,在方法丟擲異常之後執行
@Around 環繞通知,圍繞著方法執行
③在方法中宣告一個型別為JoinPoint的引數就可以訪問連結細節
ArithmeticCalculator介面
package com.spring.aop.impl;
public interface ArithmeticCalculator {
public int add(int i, int j);
public int sub(int i, int j);
public int mul(int i, int j);
public int div(int i, int j);
}
介面實現類 ArithmeticCalculatorImpl.java
package com.spring.aop.impl;
import org.springframework.stereotype.Component;
@Component
public class ArithmeticCalculatorImpl implements ArithmeticCalculator{
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
切面類 LoggingAspect.java
package com.spring.aop.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
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.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
//指定切面的優先順序,當有多個切面時,數值越小優先順序越高
@Order(1)
//把這個類宣告為一個切面:需要把該類放入到IOC容器中。再宣告為一個切面.
@Aspect
@Component
public class LoggingAspect {
/**
* 宣告切入點表示式,一般在該方法中不再新增其他程式碼。
* 使用@Pointcut來宣告切入點表示式。
* 後面的通知直接使用方法名來引用當前的切入點表示式。
*/
@Pointcut("execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))")
public void declareJoinPointExpression() {}
/**
*前置通知,在目標方法開始之前執行。
*@Before("execution(public int com.spring.aop.impl.ArithmeticCalculator.add(int, int))")這樣寫可以指定特定的方法。
* @param joinpoint
*/
@Before("declareJoinPointExpression()")
//這裡使用切入點表示式即可。後面的可以都改成切入點表示式。如果這個切入點表示式在別的包中,在前面加上包名和類名即可。
public void beforeMethod(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
List<Object>args = Arrays.asList(joinpoint.getArgs());
System.out.println("前置通知:The method "+ methodName +" begins with " + args);
}
/**
*後置通知,在目標方法執行之後開始執行,無論目標方法是否丟擲異常。
*在後置通知中不能訪問目標方法執行的結果。
* @param joinpoint
*/
@After("execution(public int com.spring.aop.impl.ArithmeticCalculator.*(int, int))")
public void afterMethod(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
//List<Object>args = Arrays.asList(joinpoint.getArgs()); 後置通知方法中可以獲取到引數
System.out.println("後置通知:The method "+ methodName +" ends ");
}
/**
*返回通知,在方法正常結束之後執行。
*可以訪問到方法的返回值。
* @param joinpoint
* @param result 目標方法的返回值
*/
@AfterReturning(value="execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))", returning="result")
public void afterReturnning(JoinPoint joinpoint, Object result) {
String methodName = joinpoint.getSignature().getName();
System.out.println("返回通知:The method "+ methodName +" ends with " + result);
}
/**
*異常通知。目標方法出現異常的時候執行,可以訪問到異常物件,可以指定在出現特定異常時才執行。
*假如把引數寫成NullPointerException則只在出現空指標異常的時候執行。
* @param joinpoint
* @param e
*/
@AfterThrowing(value="execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))", throwing="e")
public void afterThrowing(JoinPoint joinpoint, Exception e) {
String methodName = joinpoint.getSignature().getName();
System.out.println("異常通知:The method "+ methodName +" occurs exception " + e);
}
/**
* 環繞通知類似於動態代理的全過程,ProceedingJoinPoint型別的引數可以決定是否執行目標方法。
* @param point 環繞通知需要攜帶ProceedingJoinPoint型別的引數。
* @return 目標方法的返回值。必須有返回值。
*/
/*不常用
@Around("execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))")
public Object aroundMethod(ProceedingJoinPoint point) {
Object result = null;
String methodName = point.getSignature().getName();
try {
//前置通知
System.out.println("The method "+ methodName +" begins with " + Arrays.asList(point.getArgs()));
//執行目標方法
result = point.proceed();
//翻譯通知
System.out.println("The method "+ methodName +" ends with " + result);
} catch (Throwable e) {
//異常通知
System.out.println("The method "+ methodName +" occurs exception " + e);
throw new RuntimeException(e);
}
//後置通知
System.out.println("The method "+ methodName +" ends");
return result;
}
*/
}
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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <!-- 配置自動掃描包 --> <context:component-scan base-package="com.spring.aop.impl"></context:component-scan> <!-- 使AspectJ註解起作用:自動為匹配的類生產代理物件 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
Main.java
package com.spring.aop.impl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//建立spring IOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//從IOC容器中獲取bean例項
ArithmeticCalculator arithmeticCalculator = applicationContext.getBean(ArithmeticCalculator.class);
int result = arithmeticCalculator.add(4, 6);
System.out.println(result);
result = arithmeticCalculator.sub(4, 6);
System.out.println(result);
System.out.println(result);
result = arithmeticCalculator.mul(4, 6);
System.out.println(result);
System.out.println(result);
result = arithmeticCalculator.div(4, 0);
System.out.println(result);
}
}
原始碼
http://yunpan.cn/cgsrQHmUvrIQt 提取碼 6564