1. 在Spring中启用AspectJ注解支持步骤如下:
- 要在Spring应用中使用AspectJ注解,必须在classpath下包含AspectJ类库:aopalliance.jar, aspectj.weaver.jar, spring-aspects.jar和spring-aop.jar
- 将aop Scema添加到<beans>根元素中
- 要在Spring IOC容器中启用AspectJ注解支持,只要在Bean配置文件中定义一个空的XMl元素<aop:aspectj-autoproxy>
- 当Spring IOC容器侦测到Bean配置文件中的<aop:aspectj-autoproxy>元素时,会自动为与AspectJ切面匹配的Bean创建代理
2. 实现前置日志
新建Calculator接口:
public interface Calculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
新建一个CalculatorImpl类实现该接口:
import org.springframework.stereotype.Component;
@Component
public class CalculatorImpl implements Calculator {
@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类来实现日志:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//把这个类声明为一个切面:需要把该类放入到IOC容器中,再声明为一个切面
@Aspect
@Component
public class LoggingAspect {
//声明该方法是一个前置通知:在目标方法开始之间执行
@Before("execution(public int impl.Calculator.add(int, int))")
public void beforeMethod() {
System.out.println("The method begins");
}
}
其中“@Component”这个注解是把该类放入到IOC容器中,“@Aspect”这个借口是将其声明为一个切面。二者共同将该类声明为一个切面。“@Before”这个注解是声明“beforeMethod”这个方法是一个前置通知,在“public int impl.Calculator.add(int, int))”这个方法前执行。
然后配置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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="impl"></context:component-scan>
<!-- 是AspectJ注解起作用:自动为匹配的类生成代理效果 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
再在Main中调用方法:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1.创建Spring的IOC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationcontext.xml");
//2.从IOC容器中获取Bean的实例
Calculator calculator = ctx.getBean(Calculator.class);
//3.使用bean
int result = calculator.add(3, 6);
System.out.println("result:" + result);
}
}
最后得到结果如下图所示:
可以看到“The method begins”这个日志就自己自动输出了。
3. 后置通知
有了前置通知之后,后置通知的实现就很简单了,与前置通知类似,只需在目标方法前加入“@After”注解即可:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//把这个类声明为一个切面:需要把该类放入到IOC容器中,再声明为一个切面
@Aspect
@Component
public class LoggingAspect {
//声明该方法是一个前置通知:在目标方法开始之间执行
@Before("execution(public int impl.Calculator.add(int, int))")
public void beforeMethod() {
System.out.println("The method begins");
}
@After("execution(public int impl.Calculator.add(int, int))")
public void afterMethod() {
System.out.println("The method ends");
}
}
其余配置与前置通知一样
4. 返回通知
与前置通知类似,只需在目标方法前加入“@AfterReturning”注解即可
@AfterReturning(value = "execution(public int impl.Calculator.*(int, int))", returning = "result")
public void afterReturningMethod(JoinPoint joinpoint, Object result) {
String methodName = joinpoint.getSignature().getName();
System.out.println("The method "+ methodName + " ends with " + result);
}
5. 异常通知
与前置通知类似,只需在目标方法前加入“@AfterThrowing”注解即可
@AfterThrowing(value = "execution(public int impl.Calculator.*(int, int))", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinpoint, Exception ex) {
String methodName = joinpoint.getSignature().getName();
System.out.println("The method "+ methodName + " occurs excetion " + ex);
}