面向切面编程AOP[一](java 代码详解)
前言
说句实话,在工作中,使用的aop不是特别多,但是特别重要,一般是辅助程序,在现代开发者辅助程序相当重要,比如说我们需要打印一些log,但是我们不可能去卸载我们的业务程序中,因为这太。。。。。
正文
那么如何开启一个aop呢?用log举例,我们不可能去写log在我们的业务程序中,如果是这样的话,是真的难以维护。
下面实例一个需求来显示出一些问题:
/**
*需求
* 将一个方法的发生前打印出log,发生后打印log,异常打印log,要求解耦
* 通知:
* 前置通知(@Befor)
* 后置通知 (@After)
* 返回通知 (@AfterReturning)
* 异常通知 (@AfterThrowing)
* 环绕通知(@Around):动态代理,手动推进目标方法运行(joinpoint.procced)
* 步骤:
* 1.将业务逻辑组件和切面类都加入到容器中,告诉spring 哪个是切面类,开启基于注解的aop模式@EnableAspectJAutoProxy
* 2.在切面类上的每一个通知方法上标注通知注解,告诉spring 何时何地运行(切入点表达式)
首先加入容器中:
@Configuration
@EnableAspectJAutoProxy
public class MainConfigofAOP {
//业务逻辑类加入到容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
将切面类和业务逻辑类加入到容器中,然后开启切面@EnableAspectJAutoProxy。
接下来我们看下如何告诉切面注解实现类,哪个是切面,看下切面类:
/**
* 切面类
*/
@Aspect
public class LogAspects {
//公共的切入点表达式
@Pointcut("execution(public int com.axm.demo.aop.MathCalculator.*(..))")
public void pointCut(){
}
// @Before("public int com.axm.demo.aop.div(int i,int j)")
@Before("pointCut()")
public void logStart(JoinPoint joinPoint)
{
System.out.println(""+joinPoint.getSignature().getName()+"方法运行前执行,参数是:"+Arrays.asList(joinPoint.getArgs()));
}
@After("pointCut())")
public void logEnd(JoinPoint joinPoint)
{
System.out.println(""+joinPoint.getSignature().getName()+"方法运行后执行,无论是否异常都会执行");
}
@AfterReturning(value="pointCut()",returning = "result")
public void resultReturn(JoinPoint joinPoint,Object result)
{
System.out.println(""+joinPoint.getSignature().getName()+"方法成功后执行!获取返回结果:"+result);
}
@AfterThrowing(value = "pointCut()",throwing = "exception")
public void logException(JoinPoint joinPoint,Exception exception)
{
System.out.println(""+joinPoint.getSignature().getName()+"方法成功后执行!查看异常:"+exception.getMessage());
}
}
注解:@Aspect 告诉应用该类为切面类。
@Pointcut("execution(public int com.axm.demo.aop.MathCalculator.*(..))")
是公共表达式,@Before("pointCut()")表示继承pointCut方法的注解。
public int com.axm.demo.aop.MathCalculator.*(..) 表示在MathCalculator 中的所以方法将会被监听。
JoinPoint joinPoint 表示目标方法的一些信息。
这些都可以去文档中查看。
再看下业务逻辑类:
public class MathCalculator {
public int div(int i,int j){
return i/j;
}
}
业务逻辑类,就像是正常一样去书写即可,只要加入容器中。
也就是说我们在不影响现在代码的情况下,可以去实现一些辅助功能。
这里,测试一下。
@Test
public void test()
{
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigofAOP.class);
MathCalculator mathCalculator=applicationContext.getBean(MathCalculator.class);
mathCalculator.div(1,1);
}
好的,看下结果吧。
总结
即将开启源码模式。