0102-aop

背景

aop的概念不少,好比切點,通知,鏈接點,引入,織入等;實際上這是一種約定的流程;

約定編程

https://github.com/carterbrot...java

aop編程

也是按照必定規則,按照必定 流程來約定編程的;

典型場景

  • 數據庫事物

提取固定 流程,把變化的部分織入到流程中便可;git

概念

鏈接點(join point) : 即方法github

切點 (point cut): 鏈接點的範圍,哪些方法;spring

通知(advice): 分爲前置通知,後置通知,環繞通知,正常返回通知,異常返回通知數據庫

目標對象(target) :被代理對象編程

引入(introduction): 引入新的類和方法,加強現有的bean的功能springboot

織入(weaving): 經過代理技術,爲原有對象生成代理對象this

切面(aspect) : 能夠定義切點,各種通知和引用的內容google

springboot的aop的使用

@Aspect 申明切面spa

通知裏面放切點:
@Before 前置通知
@After 後置通知
@AfterReturn
@AfterThrowning
@Around

@Pointcut 定義切點
切點的指示器:

通知中的參數:
ProceedingJoinPoint jp 鏈接點信息
jp.proceed();//執行原來的方法

spring採用兩種動態代理方式,jdk的動態代理和cglib的動態代理,若是被代理類沒有實現接口,spring會切換爲cglib的動態代理;

多個切面,使用@Order(value=x) 來定義順序,前置通知從升序執行,後置通知降序執行;

例子:

package com.lifesense.ihs.tianansp.admin.interceptor;

import com.google.common.base.Strings;
import com.lifesense.ihs.tianansp.admin.core.TaAdminRestContext;
import com.lifesense.opensource.commons.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.lang.reflect.Method;


/**
 * aop
 */
@Aspect
@Service
@Order(0)
@Slf4j
public class ServiceInterceptor {

    @Pointcut("execution(public * com.lifesense.ihs.**.admin.manager..*.*(..))")
    public void pointcut() {
    }

    private String serviceName() {
        return "tiananspadmin";
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        final String methodName = method.getDeclaringClass().getCanonicalName().concat(".").concat(method.getName());
        stopWatch.start(methodName);
        Object[] args = pjp.getArgs();

        String requestId = TaAdminRestContext.get().getRequestId();

        Object returnObj = null;
        try {
            returnObj = pjp.proceed();
        } catch (Exception ex) {
            String message = String.format("[%s]服務發生系統錯誤:%s", this.serviceName(), ex.getMessage());
            log.error("{}, method:{},args:{} , ServiceContext:{}", message, methodName, JsonUtils.toJson(args), TaAdminRestContext.get(), ex);
            throw ex;
        } finally {
            stopWatch.stop();
            if (log.isDebugEnabled()) {
                log.debug("timecost_requestId:{} , args:{},returnObj:{},\n{}:", requestId, JsonUtils.toJson(args), JsonUtils.toJson(returnObj), stopWatch.prettyPrint());
            }
        }
        return returnObj;
    }
}
原創不易,轉載請註明出處,歡迎溝通交流。
本站公眾號
   歡迎關注本站公眾號,獲取更多信息