- 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式,底层使用的是动态代理技术。
一、AOP使用初探
1、导入aop模块
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
2、定义自己的业务逻辑类
- 比如定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
public class MathCalculator {
//自定义的目标方法
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
}
3、定义一个日志切面类(LogAspects)
- 要求切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行
通知方法:
- 前置通知(@Before):logStart:在目标方法(div)运行之前运行
- 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
- 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
- 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
- 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
- 切面类
@Aspect//告诉Spring当前类是一个切面类
public class LogAspects {
//抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(public int com.qiu.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
}
@After("com.qiu.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
4、将切面类和业务逻辑类(目标方法所在类)都加入到容器中
- 自定一个AOP先关的配置类并开启AOP扫面
@EnableAspectJAutoProxy//开启aop扫面
@Configuration
public class AOPConfig {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
5、测试及结果
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AOPConfig.class);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
//正常测试
mathCalculator.div(1, 1);
//异常测试
//mathCalculator.div(1, 0);
applicationContext.close();
}
结果:
div运行。。。@Before:参数列表是:{[1, 1]}
MathCalculator...div...
div结束。。。@After
div正常返回。。。@AfterReturning:运行结果:{1}
-
注意点总结:
(1)切面中需要给目标方法标注相应的通知注解
(2)必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
(3)必须把切面类和相应的业务逻辑类注入到容器中
(4)容器必须开启开启AOP模式,给配置类中加 @EnableAspectJAutoProxy
网友评论