切面编程
代码地址:
切面执行顺序
Spring5以后顺序就一切正常
正常:前置通知===目标方法===返回通知===后置通知
异常: 前置通知===目标方法===异常通知===后置通知
try{
前置通知
目标方法的执行
返回通知
}catch(){
异常通知
}finally{
后置通知
}
1、使用注解形式
-
定义注解
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
public String title() default "11";
}
-
定义切面
@Aspect
@Component
public class LogAspect2 {
/**
* 处理请求前执行
*/
@Before(value = "@annotation(controllerLog)")
public void boBefore(JoinPoint joinPoint, Log controllerLog) {
System.out.println(controllerLog.title());
String name = joinPoint.getSignature().getName();
System.out.println("前置logStart()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】");
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
System.out.println(controllerLog.title());
String name = joinPoint.getSignature().getName();
System.out.println("返回logReturn()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】【result: "+jsonResult+"】");
}
//后置通知
@After(value = "@annotation(controllerLog)")
public void logEnd(JoinPoint joinPoint, Log controllerLog){
System.out.println(controllerLog.title());
String name = joinPoint.getSignature().getName();
System.out.println("后置logEnd()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】");
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
System.out.println(controllerLog.title());
String name = joinPoint.getSignature().getName();
System.out.println("异常logError()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】【exception: "+e+"】");
}
}
-
定义目标
@Component
public class HelloService {
@Log
public String sayHello(String name){
String result = "你好:"+name;
System.out.println(result);
int length = name.length();
return result + "---" + length;
}
}
-
配置类
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.orbit.aop")
public class MainConfig {
}
-
测试类
public class AnnotationMainTest {
public static void main(String[] args) {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
HelloService helloService = applicationContext.getBean(HelloService.class);
helloService.sayHello("zhangsan");
}
}
-
没有异常
11
前置logStart()==>sayHello....【args: [zhangsan]】
你好:zhangsan
11
返回logReturn()==>sayHello....【args: [zhangsan]】【result: 你好:zhangsan---8】
11
后置logEnd()==>sayHello....【args: [zhangsan]】
-
有异常
11
前置logStart()==>sayHello....【args: [zhangsan]】
你好:zhangsan
11
异常logError()==>sayHello....【args: [zhangsan]】【exception: java.lang.ArithmeticException: / by zero】
11
后置logEnd()==>sayHello....【args: [zhangsan]】
Exception in thread "main" java.lang.ArithmeticException: / by zero
2、使用切入点表达式
切入点表达式语法
语法结构:
execution([
权限修饰符
] [
返回类型
] [
类全路径
] [
方法名称
]([
参数列表
]) )
举例 :对 com.orbit.aop.service.HelloService类里面的 sayHello进行增强
execution(* com.orbit.aop.service.HelloService.sayHello(..))
-
定义切面
@Aspect //说明这是切面
@Component //切面也是容器中的组件
public class LogAspect {
//前置通知 增强方法/增强器
@Before("execution(* com.orbit.aop.service.HelloService.sayHello(..))")
public void logStart(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("前置logStart()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】");
}
//返回通知
@AfterReturning(value = "execution(* com.orbit.aop.service.HelloService.sayHello(..))",returning = "result")
public void logReturn(JoinPoint joinPoint,Object result){
String name = joinPoint.getSignature().getName();
System.out.println("返回logReturn()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】【result: "+result+"】");
}
//后置通知
@After("execution(* com.orbit.aop.service.HelloService.sayHello(..))")
public void logEnd(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("后置logEnd()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】");
}
//异常
@AfterThrowing(value = "execution(* com.orbit.aop.service.HelloService.sayHello(..))",throwing = "e")
public void logError(JoinPoint joinPoint,Exception e){
String name = joinPoint.getSignature().getName();
System.out.println("异常logError()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】【exception: "+e+"】");
}
}
补充 around
@Aspect
@Component
public class LogAspectAround {
@Around(value = "@annotation(controllerLog)")
public Object doAfterThrowing(ProceedingJoinPoint joinPoint, Log controllerLog) {
System.out.println(controllerLog.title());
System.out.println(joinPoint.getArgs());
System.out.println("环绕前置通知");
Object proceed = null;
try {
proceed = joinPoint.proceed();
} catch (Throwable e) {
System.out.println("环绕异常通知");
throw new RuntimeException(e);
}finally {
System.out.println("环绕最终通知");
}
System.out.println("环绕后置通知");
return proceed;
}
/**
* 11
* [Ljava.lang.Object;@463fd068
* 环绕前置通知
* 你好:zhangsan
* 环绕异常通知
* 环绕最终通知
*/
}
没有异常
前置logStart()==>sayHello....【args: [zhangsan]】
你好:zhangsan
返回logReturn()==>sayHello....【args: [zhangsan]】【result: 你好:zhangsan---8】
后置logEnd()==>sayHello....【args: [zhangsan]】
有异常
前置logStart()==>sayHello....【args: [zhangsan]】
你好:zhangsan
异常logError()==>sayHello....【args: [zhangsan]】【exception: java.lang.ArithmeticException: / by zero】
后置logEnd()==>sayHello....【args: [zhangsan]】