一个简单的例子实现自己的AOP

AOP是Aspect Oriented Programming的缩写,意思是面向切面编程,与OOP(Object Oriented Programming)面向对象编程对等,都是一种编程思想。

从OOP角度分析,我们关注业务的处理逻辑,是属于纵向的行为,从AOP角度分析,我们关注对象行为发生时的问题,是属于横向的行为。

AOP 作用:

1 监控函数的调用

2 捕获异常发生

实际应用在:事务、安全、日志等横切关注。

下面是aop打印service层的方法日志为例:

/**
 * @功能描述: Service层日志/异常切面类
 */
@Component
@Aspect
public class ApiServiceAspect {

    private final Logger logger = Logger.getLogger(this.getClass());

    /**
     * 切面
     */
    private final String POINT_CUT = 
        "execution(* com.demo.bigdata.service.*.*.*(..))";

    @Pointcut(POINT_CUT)
    private void pointcut(){}

    @Before(value = POINT_CUT)
    public void before(JoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        StringBuilder log = new StringBuilder();
        log.append("before: ")
                .append(className)
                .append("@")
                .append(methodName)
                .append(" , params: ");
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            log.append(JSONObject.toJSONString(arg) + ", ");
        }
        logger.info(log.toString());
    }

    @AfterReturning(value = "pointcut()", returning = "returnObj")
    public void afterReturn(Object returnObj) {
        String result = JSONObject.toJSONString(returnObj);
        logger.info("afterReturning: "+result);
    }

    @AfterThrowing(value = POINT_CUT, throwing = "e")
    public void afterThrowing(Throwable e) {
        logger.error("afterThrowing: "+e.getMessage(), e);
    }

    @Around(value = "pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) 
        throws Throwable {
        Long begin = System.currentTimeMillis();
        StringBuilder log = new StringBuilder("around: ");
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Exception e) {
            logger.error(log + e.getMessage(), e);
        }
        Long end = System.currentTimeMillis();
        log.append(" 执行时间: ")
                .append(end-begin)
                .append("ms");
        return result;
    }

} 

配置文件使其生效

<context:component-scan base-package="com.demo.bigdata" />

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

如果使用了spring mvc后,如果把<aop:aspectj-autoproxy proxy-target-class="true"/>放在application.xml文件中可能会aop无效,最好把它放在dispatcher-servlet.xml文件中。

原文发布于微信公众号 - java工会(javagonghui)

原文发表时间:2018-05-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT杂记

Java Process destroy方法kill进程,返回码测试

Java代码: package com.spiro; import java.io.IOException; public class Main { ...

18410
来自专栏Jed的技术阶梯

Kafka 新版消费者 API(三):以时间戳查询消息和消费速度控制

kafka 在 0.10.1.1 版本增加了时间索引文件,因此我们可以根据时间戳来访问消息。 如以下需求:从半个小时之前的offset处开始消费消息,代码示例...

3502
来自专栏玩转JavaEE

Spring Cloud中Hystrix的请求缓存

高并发环境下如果能处理好缓存就可以有效的减小服务器的压力,Java中有许多非常好用的缓存工具,比如Redis、EHCache等,当然在Spring Cloud的...

3438
来自专栏流媒体

Json海量数据解析Json海量数据解析

​ 在android开发中,app和服务器进行数据传输时大多数会用到json。在解析json中通常会用到以下几种主流的解析库:jackson、gson、fa...

742
来自专栏面朝大海春暖花开

redis实现分布式锁工具类 灰常好用

1192
来自专栏白驹过隙

ACE - Reactor实现I/O,Dispatch,Service三层完整服务器(完结)

35517
来自专栏Jack的Android之旅

刨解OkHttp之访问连接

因为OkHttp能讲的东西太多了,上一篇文章只是讲到了他的设计架构即责任链模式和异步多线程网络访问,这对于OkHttp只是冰山一角,对于一个网络请求框架,最重要...

601
来自专栏奔跑的蛙牛技术博客

并发知识5

锁和条件不能解决线程中的所有问题 账户1:200; 账户2:300; 线程1:从账户1转移300到账户2 线程2: 从账户2转移400到账户1 线程一和线...

702
来自专栏Jed的技术阶梯

zookeeper案例之4个逻辑思维训练小题目

632
来自专栏码匠的流水账

reactor-netty中TcpClient的newHandler过程

本文主要研究一下reactor-netty中TcpClient的newHandler过程

541

扫码关注云+社区