Spring AOP源码分析--代理方式的选择

能坚持别人不能坚持的,才能拥有别人未曾拥有的。
关注编程大道公众号,让我们一同坚持心中所想,一起成长!!

 

年前写了一个面试突击系列的文章,目前只有redis相关的。在这个系列里,我整理了一些面试题与大家分享,帮助年后和我一样想要在金三银四准备跳槽的同学。我们一起巩固、突击面试官常问的一些面试题,加油!!





什么是 AOP ?

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

Spring AOP源码分析--代理方式的选择

Spring AOP面向切面编程 接口调用耗时

现在我们有个接口要在日志中记录接口耗时,我们会怎么做呢?一般我们会在接口开始和接口结束时获取系统时间,然后二者一减就是接口耗时时间了。如下,在20行我们打印出接口耗时。

1@RestController
2@Slf4j
3public class LoginController {
4    @Autowired
5    LoginService loginService;
6    @RequestMapping("/login/{id}")
7    public Map<String,Object> login(@PathVariable("id") Integer id){
8        long start = System.currentTimeMillis();
9        Map<String,Object> result = new HashMap<>();
10        result.put("status","0");
11        result.put("msg" , "失败");
12        if (loginService.login(id)) {
13            result.put("status","1");
14            result.put("msg" , "成功");
15        }
16        long end = System.currentTimeMillis();
17        log.info("耗时=>{}ms",end-start);
18        return result;
19    }
20}

启动类:

1@SpringBootApplication
2public class SpringaopSbApplication {
3    public static void main(String[] args) {
4        SpringApplication.run(SpringaopSbApplication.class, args);
5    }
6}

但是,如果所有接口都要记录耗时时间呢?我们还按这种方式吗?显然不行,这种要在每个接口都加上同样的代码,而且如果后期你老板说去掉的话,你还有一个个的删掉么?简直是不可想象。。
所以对于这种需求,其实是可以提炼出来的。我们想,统计接口的耗时时间,无非就是在接口的执行前后记录一下时然后相减打印出来即可,然后在这样的地方去加入我们提炼出来的公共的代码。这就好比在原来的业务代码的基础上,把原来的代码横切开来,在需要的地方加入公共的代码,对原来的业务代码起到功能增强的作用。
这就是AOP的作用。

Spring AOP应用场景 - 接口耗时记录

下面我们来看看使用Spring AOP怎么满足这个需求。

首先定义一个切面类TimeMoitor,其中pointCut()方法(修饰一组连接点)是一个切点,@Pointcut定义了一组连接点(使用表达式匹配)
aroundTimeCounter()是要加入的功能,被@Around注解修饰,是一个环绕通知(Spring AOP通知的一种),其实就是上面说的在方法执行前后记录时间然后相减再打印出来耗时时间。

1@Aspect
2@Component
3@Slf4j
4public class TimeMoitor {
5    @Pointcut(value = "execution(* com.walking.springaopsb.controller.*.*(..))")
6    public void pointCut(){}
7
8    @Around(value = "com.walking.springaopsb.aop.TimeMoitor.pointCut()")
9    public Object aroundTimeCounter(ProceedingJoinPoint jpx){
10        long start = System.currentTimeMillis();
11        Object proceed = null;
12        try {
13             proceed = jpx.proceed();
14        } catch (Throwable throwable) {
15            throwable.printStackTrace();
16        }
17        long end = System.currentTimeMillis();
18        log.info("耗时=>{}ms",end-start);
19        return proceed;
20    }
21}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsswww.html