spring--aop--02--纯注解实现
一、实现aop的三步:
- 创建目标类与切面类,加入到Spring容器中,并指明切面类
- 在切面类方法上标注通知注解
- 开启注解版aop模式
二、配置类实现AOP代码
(1)配置类
package com.fuping3.aopconfig;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = {"com.fuping3.aopconfig"})
/**
* @EnableAspectJAutoProxy 表示开启注解版aop的注解
* 备注:
* 1、proxyTargetClass默认为false--表示使用jdk代理
* 2、proxyTargetClass = true表示使用cglib代理,当jdk代理不可用时仍使用cglib代理
*/
//
//@EnableAspectJAutoProxy
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class MyAopConfig {
}
(2)Java代码
package com.fuping3.aopconfig;
public interface IUser {
int div(int i, int j);
}
package com.fuping3.aopconfig;
import org.springframework.stereotype.Component;
@Component
public class User implements IUser{
public int div(int i,int j){
System.out.println("目标方法执行...");
return i/j;
}
}
package com.fuping3.aopconfig;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(2)
public class Proxy2 {
@Before(value = "execution(* com.fuping3.aopconfig.User.div(..))")
public void proxyBefore(){
System.out.println("------beforeProxy2.....");
}
}
package com.fuping3.aopconfig;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@Aspect //指明这是一个切面类
@Order(1) //有多个切面类时,使用Order注解指明优先级,数字越小优先级越高
public class UserProxy {
/**
* 将公共的切入点表达式抽取为公共的,使用@Pointcut注解
*/
@Pointcut(value = "execution(* com.fuping3.aopconfig.User.div(..))")
public void pointDemo(){}
@Before("pointDemo()")
public void beforeDiv(){
System.out.println("--------beforeDiv...");
}
/**
* 后置通知(最终通知)--方法正常执行、异常执行都会执行,类似finally
*/
@After("pointDemo()")
public void afterDiv(){
System.out.println("--------afterDiv...");
}
/**
* 环绕通知--方法执行前后都执行,包括异常时
* @param joinPoint
* @return
*/
@Around(value = "pointDemo()")
public Object aroundDiv(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("----------anno around div before...");
System.out.println("方法名称:"+joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
System.out.println("参数列表"+ Arrays.toString(args));
Object obj;
obj=joinPoint.proceed();
/* try {
obj=joinPoint.proceed();
} catch (Throwable e) {
obj=null;
System.out.println("方法执行异常"+e);
}*/
System.out.println("anno around div after...");
return obj;
}
/**
* 返回通知--方法返回后进行的增强--方法正常执行会执行,异常执行不会执行
* returning给被增强方法返回值取个名字,给后面引用
*
* 备注:
* 1、@AfterReturning如果和@Around一起使用,那么就需要给@Around的方法设置返回参数,因为@AfterReturning接收到的值其实是@Around返回的。
* 2、@AfterReturning如果和@Around一起使用,若@Around中obj=joinPoint.proceed();使用try...catch捕获处理了异常,则有异常时:
* (a)该方法还是执行;
* 并且
* (b)会导致@AfterThrowing增强不执行
* JoinPoint必须为第一个参数
* @param
* @param result
*/
@AfterReturning(value ="pointDemo()",returning="result")
public void afterReturningDiv(JoinPoint joinPoint,Object result){
System.out.println("-----------anno afterReturning div...");
System.out.println("方法名称:"+joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
System.out.println("参数列表"+ Arrays.toString(args));
System.out.println("返回值:"+result);
}
/**
* 异常增强--有异常时执行的增强
* throwing用于指定异常的参数名
* @param joinPoint
* @param exception
*/
@AfterThrowing(value ="pointDemo()",throwing="exception")
public void afterDiv(JoinPoint joinPoint,Exception exception){
System.out.println("------------anno afterThrowing div...");
System.out.println("方法名称:"+joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
System.out.println("参数列表"+ Arrays.toString(args));
System.out.println("异常值:"+exception);
}
}
(3)测试代码
package com.fuping3.aopconfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Client {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyAopConfig.class);
IUser user= (IUser) context.getBean("user");
Object userProxy = context.getBean(UserProxy.class);
user.div(10,0);
System.out.println(user.getClass());
System.out.println(userProxy.getClass());
}
}
(4)输出结果
----------anno around div before...
方法名称:div
参数列表[10, 0]
--------beforeDiv...
------beforeProxy2.....
目标方法执行...
--------afterDiv...
------------anno afterThrowing div...
方法名称:div
参数列表[10, 0]
异常值:java.lang.ArithmeticException: / by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.fuping3.aopconfig.User.div(User.java:9)
at com.fuping3.aopconfig.User$$FastClassBySpringCGLIB$$12d07ebe.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)