博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码(3) - Spring AOP入门
阅读量:4165 次
发布时间:2019-05-26

本文共 7932 字,大约阅读时间需要 26 分钟。

Spring-AOP

没有AOP带来的问题

public interface LeviService {

   

    public boolean problem1();

   

    public boolean problem2();

   

}

@Service

public class LeviServiceImpl implements LeviService {

 

    @Override

    public boolean problem1() {

         System.out.println("problem1 访问开始时间:" + System.currentTimeMillis());

 

         System.out.println("执行业务逻辑。。。");

        

         System.out.println("problem1 访问结束时间:" + System.currentTimeMillis());

         return true;

    }

   

    @Override

    public boolean problem2() {

         System.out.println("problem2 访问开始时间:" + System.currentTimeMillis());

 

         System.out.println("执行业务逻辑。。。");

        

         System.out.println("problem2 访问结束时间:" + System.currentTimeMillis());

         return true;

    }

}

@Configuration

@ComponentScan(value = "com.levi.spring.aop.levi01base")

public class MainConfig {

   

    /**

     * 传统OOP的问题:执行结果会发现每个方法都会去执行这个时间的方法,这样就造成了代码冗余以及难以维护。

     */

    public static void main(String[] args) {

         AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

        

         LeviService leviService = annotationConfigApplicationContext.getBean(LeviServiceImpl.class);

        

        

         leviService.problem1();

         leviService.problem2();

        

         annotationConfigApplicationContext.close();

    }

}

 

 

 

pom.xml新增

         <!-- AOP切面 -->

         <dependency>

             <groupId>org.springframework</groupId>

             <artifactId>spring-aspects</artifactId>

             <version>5.0.6.RELEASE</version>

         </dependency>

 

AOP编程开始

与传统的OOP(Object Oraentd Programming)面向对象对比,传统的OOP开发中的代码逻辑是自上而下的,在这些自上而下的代码中会产生横切面的问题,而这些横切面又与主业务逻辑关系不大,但是会散落在代码的各个地方,造成难以维护。

AOP的编程思想就是把这些横切性的问题和主业务逻辑进行分离,从而起到了解耦的目的。比如在每一个Service或Controller方法上加上日志打印,那么就要在每个方法都加上这个打印了,而如果用AOP就可以直接定位到这个包,只要访问这个包下的方法就会统一执行这个日志打印。

 

public interface LeviService {

   

    public boolean problem1(int i);

   

    public boolean problem2();

   

    public int myException(int i) throws Exception;

}

@Service

public class LeviServiceImpl implements LeviService {

 

    @Override

    public boolean problem1(int i) {

//      System.out.println("problem1 访问开始时间:" + System.currentTimeMillis());

 

         System.out.println("执行业务逻辑。。。" + i);

        

//       System.out.println("problem1 访问结束时间:" + System.currentTimeMillis());

         return true;

    }

   

    @Override

    public boolean problem2() {

//       System.out.println("problem2 访问开始时间:" + System.currentTimeMillis());

 

         System.out.println("执行业务逻辑。。。");

        

//       System.out.println("problem2 访问结束时间:" + System.currentTimeMillis());

         return true;

    }

 

    @Override

    public int myException(int i) throws Exception {

         System.out.println("执行业务逻辑。。。" + i);

         if(i == 5) {

             throw new Exception("抛出异常了...");

         }

         return 1;

    }

}

/**

 * 日志切面:

 * @Before:在目标方法之前执行

 * @After:在目标方法执行之后执行

 * @AfterReturning:在目标方法返回之前执行

 * @AfterThrowing:在目标方法抛出异常之后执行,如果异常在@Around捕捉了,那么就不会执行了

 * @Around:在执行方法之前前后执行

 */

@Aspect

@Component

public class LogAopAspects1 {

   

    /**

     * 在目标方法开始之前执行

     */

//  @Before("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    @Before("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    public void before(JoinPoint joinpoint) {

         System.out.println("@Before" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()));

    }

   

    /**

     * 在目标方法执行完成之后执行

     */

    @After("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    public void after(JoinPoint joinpoint) {

         System.out.println("@After" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()));

    }

   

    /**

     * 目标方法执行完成之后的返回

     */

    @AfterReturning(value="execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))",returning = "result")

    public void afterReturning(JoinPoint joinpoint,Object result) {

         System.out.println("@AfterReturning" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()) + " - 结果:" + result);

    }

   

    /**

     * 目标方法抛出异常之后执行

     */

    @AfterThrowing(value="execution(public int com.levi.spring.aop.levi02aopbase.LeviService.myException(..))",throwing = "exception")

    public void afterThrowing(JoinPoint joinpoint,Exception exception) {

         System.out.println("@AfterThrowing" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()));

    }

   

    /**

     * 在一个方法之前和执行后的操作

     */

    @Around("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

         System.out.println("@Around:调用执行方法之前的执行时间:" + System.currentTimeMillis());

        

         try {

             proceedingJoinPoint.proceed(); //执行目标方法

         } catch (Throwable e) {

             System.out.println("@Around:执行目标方法报错");

             //抛出异常,验证@AfterThrowing

//           throw e;

         }

        

         System.out.println("@Around:调用执行方法之后的执行时间:" + System.currentTimeMillis());

    }

}

@Configuration

@EnableAspectJAutoProxy

@ComponentScan(value = "com.levi.spring.aop.levi02aopbase")

public class MainConfig {

 

    /**

     * Aop编程:与传统的OOPObject Oraentd Programming)面向对象对比,传统的OOP开发中的代码逻辑是自上而下的,

     * 在这些自上而下的代码中会产生横切面的问题,而这些横切面又与主业务逻辑关系不大,但是会散落在代码的各个地方,造成难以维护。

     * AOP的编程思想就是把这些横切性的问题和主业务逻辑进行分离,从而起到了解耦的目的。

     * 比如在每一个ServiceController方法上加上日志打印,那么就要在每个方法都加上这个打印了,而如果用AOP就可以直接定位

     * 到这个包,只要访问这个包下的方法就会统一执行这个日志打印。

     *

     * 1、定义好AOP切面类,并写好对应的切点(execution

     * 2、将AOP切面类和业务类放入容器中(代码中:@Component@Service

     * 3、基于注解开启AOP@EnableAspectJAutoProxy

     */

    public static void main(String[] args) throws Exception {

         AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

        

         /*

          * 首次执行会发现为什么AOP没有起作用。

          * AOP是相当于一个Spring功能模块,要用这个功能模块要开启才行。

          * 要在MainConfig中加上@EnableAspectJAutoProxy

          *

          * 加了@EnableAspectJAutoProxy发现还是不行。

          * 还要在对应的AOP配置类中,标识说明这个类是AOP编程的类

          * LogAopAspects1中加上@Aspect

          */

        

         LeviService leviService = annotationConfigApplicationContext.getBean(LeviService.class);

         leviService.myException(3);

        

         annotationConfigApplicationContext.close();

    }

}

/**

 * 日志切面:

 * @Before:在目标方法之前执行

 * @After:在目标方法执行之后执行

 * @AfterReturning:在目标方法返回之前执行

 * @AfterThrowing:在目标方法抛出异常之后执行,如果异常在@Around捕捉了,那么就不会执行了

 * @Around:在执行方法之前前后执行

 *

 * 〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓

 *

 * LogAopAspects1的写法太麻烦了,如果每个方法都要这样写的话,是否又会出现大量的冗余,那样的话就也只是简化了一点冗余而已。

 * LogAopAspects2的新写法

 * @Pointcut:点切,指定点

 */

@Aspect

@Component

public class LogAopAspects2 {

   

    @Pointcut("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    public void pointCut() {

         System.out.println("@Pointcut");

    };

   

    /**

     * 在目标方法开始之前执行

     */

//  @Before("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    @Before("pointCut()")

    public void before(JoinPoint joinpoint) {

         System.out.println("@Before" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()));

    }

   

    /**

     * 在目标方法执行完成之后执行

     */

//  @After("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    @After("pointCut()")

    public void after(JoinPoint joinpoint) {

         System.out.println("@After" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()));

    }

   

    /**

     * 目标方法执行完成之后的返回

     */

//  @AfterReturning("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    @AfterReturning(value="pointCut()",returning = "result")

    public void afterReturning(JoinPoint joinpoint,Object result) {

         System.out.println("@AfterReturning" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()) + " - 结果:" + result);

    }

   

    /**

     * 目标方法抛出异常之后执行

     */

//  @AfterThrowing(value="execution(public void com.levi.spring.aop.levi02aopbase.LeviService.myException(..))",throwing = "exception")

    @AfterThrowing(value="pointCut()",throwing = "exception")

    public void afterThrowing(JoinPoint joinpoint,Exception exception) {

         System.out.println("@AfterThrowing" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()));

    }

   

    /**

     * 在一个方法之前和执行后的操作

     */

//  @Around("execution(public void com.levi.spring.aop.levi02aopbase.LeviService.*(..))")

    @Around("pointCut()")

    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

         System.out.println("@Around:调用执行方法之前的执行时间:" + System.currentTimeMillis());

        

         try {

             proceedingJoinPoint.proceed(); //执行目标方法

         } catch (Throwable e) {

             System.out.println("@Around:执行目标方法报错");

             //抛出异常,验证@AfterThrowing

//           throw e;

        }

        

         System.out.println("@Around:调用执行方法之后的执行时间:" + System.currentTimeMillis());

    }

}

转载地址:http://zqmxi.baihongyu.com/

你可能感兴趣的文章
如果函数传递的是结构体,小心在调用的参数中给指针重新赋值(拿tm结构体举例)
查看>>
使用nm命令获取linux的可执行文件里或动态库中的所有函数名称
查看>>
动态库编写 头文件.h注意事项
查看>>
多个动态库的依赖问题(先后顺序务必注意)
查看>>
二叉树的最大深度
查看>>
N 叉树的最大深度
查看>>
剑指 Offer 52. 两个链表的第一个公共节点 & 相交链表
查看>>
剑指offer 03.数组中的重复数字(四种办法!哎,就是全!)
查看>>
三层--对你的认识再多一点
查看>>
数据库初级篇--EA & ER & SQL Server
查看>>
离线安装.net framework3.5
查看>>
抽象工厂+反射(一)
查看>>
12月英语--Sowing
查看>>
泛型--datatable TO List
查看>>
存储过程
查看>>
C#之导出excel
查看>>
版本控制--SVN
查看>>
泛型 VS Data Table
查看>>
CSS盒子模型
查看>>
HTML总结(一)
查看>>