版权声明:仅供学习交流使用 https://blog.csdn.net/drxRose/article/details/84801102
使用@AspectJ,需要额外导入jar包,从官网下载即可,搜索关键字`aspectj download`.
说明,在有些参考书中,advice译为`增强`,依据其效用.
@Aspect | 定义一个切面 |
@PointCut | 定义复用指示器 |
@Before | 前置通知 |
@After | 后置通知 |
@Around |
环绕通知 |
@AfterReturning | 返回通知 |
@AfterThrowing | 异常通知 |
目标对象类
package siye;
import org.springframework.stereotype.Component;
@Component
public class TargetObj
{
// 测试前置通知和后置通知
public void work()
{
System.out.println("user_work");
}
// 测试异常通知.
public void throwMethod()
{
throw new RuntimeException();
}
// 测试环绕通知.
public void testAround()
{
System.out.println("test_around_advice");
}
// 测试返回通知,和参数截取.
public int testReturn(int num)
{
return num;
}
}
测试@AspectJ注解的切面类
package siye;
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 AspectJtoAnno
{
@Pointcut("execution(* *.work(..))") // 定义可重用的指示器.
public void myPointCut()
{
}
/*
* 前置通知和后置通知.
*/
@Before("myPointCut()")
public void testAnnoBefore()
{
System.out.println("方法即将执行----advice_before");
}
@After("myPointCut()")
public void testAnnoAfter()
{
System.out.println("方法执行完毕-----advice_after");
}
/*
* 环绕通知.
*/
@Around("execution(* *.testAround(..))")
public void testAnnoAround(ProceedingJoinPoint jp)
{
// ProceedingJoinPoint,唯一作用,通知中,调用被通知的方法.
// 不调用,该通知阻塞被通知方法的调用.
try
{
System.out.println("方法开始执行----advice_around");
jp.proceed();
System.out.println("方法执行完毕----advice_around");
} catch (Throwable e)
{
}
}
/*
* 异常通知.
*/
@AfterThrowing("execution(* *.throwMethod(..))")
public void testAnnoAfterThrowing()
{
System.out.println("方法抛出异常----advice_throwing");
}
/*
* 返回通知和参数的获取.
*/
/**
* 提取方法中的参数.
* name binding only allowed in target, this, and args pcds
*
* execution和args组合使用
*/
@AfterReturning("execution(* *.testReturn(int)) && args(num)")
public void testAnnoAfterReturning(int num)
{
System.out.println("提取出来的参数值是" + num);
System.out.println("方法正确执行已返回-----after_returning");
}
}
上下文配置类
package siye;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class ConfigClass
{
}
测试注解类
package siye;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* advice使用的5个注解.
* org.aspectj.lang.annotation.After;
* org.aspectj.lang.annotation.AfterReturning;
* org.aspectj.lang.annotation.AfterThrowing;
* org.aspectj.lang.annotation.Around;
* org.aspectj.lang.annotation.Before;
*
* 切面使用的注解.
* org.aspectj.lang.annotation.Aspect;
*/
public class UnitTest
{
public static void main(String[] args)
{
String packName = UnitTest.class.getPackage().getName();// 反射获取包名称.
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(ConfigClass.class);
context.scan(packName);// 取代@ComponentScan.
context.refresh();
// System.out.println(context);
TargetObj targetObj = context.getBean(TargetObj.class);
targetObj.work();
targetObj.testAround();
targetObj.testReturn(12);
try
{
System.out.println();
targetObj.throwMethod();
} catch (Exception e)
{
}
context.close();
}
}