一、实现aop的三步:
- 创建目标类与切面类,加入到Spring容器中,并指明切面类
- 在切面类方法上标注通知注解
- 开启注解版aop模式
二、aop注解版实现代码
spring配置文件代码
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启注解扫描,用于扫描bean,IOC部分内容-->
<context:component-scan base-package="com.fuping3.aopanno"/>
<!--开启注解版aop-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
java代码:
package com.fuping3.aopanno;
import org.springframework.stereotype.Component;
@Component
public class User{
public int div(int i,int j){
System.out.println("目标方法执行...");
return i/j;
}
}
package com.fuping3.aopanno;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@Aspect//使用@Aspect注解,表示该类是切面类
public class UserProxy {
/**
* 将公共的切入点表达式抽取为公共的,使用@Pointcut注解
*/
@Pointcut(value = "execution(* com.fuping3.aopanno.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;
}
/**
* 返回通知--方法返回后进行的增强--方法正常执行会执行,异常执行不会执行
* JoinPoint必须出现在第一个参数位置
* returning给被增强方法返回值取个名字,给后面引用
*
* 备注:
* 1、@AfterReturning如果和@Around一起使用,那么就需要给@Around的方法设置返回参数,因为@AfterReturning接收到的值其实是@Around返回的。
* 2、@AfterReturning如果和@Around一起使用,若@Around中obj=joinPoint.proceed();使用try...catch捕获处理了异常,则有异常时:
* (a)该方法还是执行;
* 并且
* (b)会导致@AfterThrowing增强不执行
* @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);
}
}
测试代码:
package com.fuping3.aopanno;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext=
new ClassPathXmlApplicationContext("bean2.xml");
User user = applicationContext.getBean("user", User.class);
user.div(10, 2);
}
}
输出结果
----------anno around div before...
方法名称:div
参数列表[10, 2]
--------beforeDiv...
目标方法执行...
anno around div after...
--------afterDiv...
-----------anno afterReturning div...
方法名称:div
参数列表[10, 2]
返回值:5
Process finished with exit code 0