spring aop用法

介紹


在開發(fā)中我們經常使用oop這種縱向結構來開發(fā)蹂随,但是卻會出現一些橫切的功能十嘿。譬如,日志記錄的功能岳锁,我們需要在每個方法執(zhí)行的詳細信息通過日志記錄绩衷,但是我們?yōu)槊總€方法去寫日志,明顯不合理激率。再如異常處理功能咳燕,我們需要在每個方法執(zhí)行拋出的異常都專門處理都不合理蓝翰。這樣就需要AOP面向切面開發(fā)來處理橫切問題豁生。

AOP術語


  1. 通知(advice):
    通知主要是定義切面是什么以及何時使用逞度。
    Before:在接合點之前執(zhí)行通知抬旺。
    AfterReturning:在接合點執(zhí)行完成之后執(zhí)行通知。
    AfterThrowing:如果從接合點拋出了任何異常译暂,都執(zhí)行通知永淌。
    After:接合點執(zhí)行完成之后,無論是否拋出了異常健爬,都執(zhí)行通知。
    Around:在接合點周圍執(zhí)行通知么介,意思就是可能在接合點之前執(zhí)行娜遵,也可能在接合點之后執(zhí)行。
  2. 連接點(join point):
    意思就是代碼中的點壤短,在這個點上開始玩切面设拟。效果肯定是向應用程序中插入額外的邏輯。
  3. 切點(point cut):
    用來選擇需要執(zhí)行一個或者多個連接點的表達式久脯。
  4. 切面(aspect):
    切面就是切點和通知的結合纳胧。
  5. 織入(weaving):
    將方面與目標對象結合在一起的過程。
  6. 引入(introduce):
    動態(tài)地為已經存在的類添加屬性和方法帘撰。

XML方式實現AOP


配置文件:

    <context:component-scan base-package="cn.spy"></context:component-scan>
    <context:annotation-config></context:annotation-config>
    <aop:config>
        <aop:pointcut expression="execution(* cn.spy.service.impl.MyServiceImpl.*(..))" id="pc"/>
        <aop:aspect ref="myAop">
            <aop:before method="beforeExecute" pointcut-ref="pc"/>
            <aop:after method="afterExecute" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>

強制設置使用cglib代理:<aop:config proxy-target-class="true">

業(yè)務類和接口

public interface MyService {
    public void serviceMed();
}

@Component("myService")
public class MyServiceImpl extends BaseLog implements MyService{

    @Override
    public void serviceMed() {
        System.out.println("業(yè)務邏輯方法");
    }
}

切面類:

@Component("myAop")
public class MyAop extends BaseLog {
    
    public void beforeExecute() {
        System.out.println("before execute");
    }
    
    public void afterExecute() {
        System.out.println("after execute");
    }
}

測試類:

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        MyService myService = (MyService) context.getBean("myService");
        myService.serviceMed();
    }

結果:


1.jpg

注解方式實現AOP


切面類:

@Component("myAop")
@Aspect
public class MyAop extends BaseLog {
    
    @Pointcut("execution(* cn.spy.service.impl.MyServiceImpl.*(..))")
    public void cutMethod() {
        
    }
    
    @Before("cutMethod()")
    public void beforeExecute() {
        System.out.println("before execute");
    }
    
    @After("cutMethod()")
    public void afterExecute() {
        System.out.println("after execute");
    }
}

強制使用cglib代理:@EnableAspectJAutoProxy(proxyTargetClass=true)

aop自定義注解實現記錄操作日志


  1. 自定義注解
/**
 * 日志操作注解
 */
@Documented
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogOperation {
    /**
     *  操作所屬的模塊
     * @return
     */
    public String module() default "";

    /**
     * 操作
     * @return
     */
    public String operation() default "";

}
  1. 實現切面類
@Slf4j
@Component
@Aspect
public class LogAspect {

    @Autowired
    private MachineBO machine;

    @Autowired
    private LogMapper logMapper;

    @Pointcut("@annotation(com.sunpy.permissionservice.log.LogOperation)")
    public void logPoint() {

    }

    @AfterReturning(pointcut = "logPoint()", returning = "result")
    public void doLog(JoinPoint joinPoint, Object result) {
        // 從切面織入點處通過反射機制獲取織入點處的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 獲取切入點所在的方法
        Method method = signature.getMethod();
        // 獲取請求的類名
        String className = joinPoint.getTarget().getClass().getName();
        
        LogOperation logOperation = method.getAnnotation(LogOperation.class);

        Log log = new Log();
        log.setLogModule(logOperation.module());
        log.setLogOperation(logOperation.operation());
        log.setLogClazz(className);
        log.setLogMethod(method.getName());
        log.setLogMethodResult(method.getReturnType().getName());
        StringBuilder sb = new StringBuilder();

        for (Parameter parameter : method.getParameters()) {
            sb.append(parameter.getParameterizedType().getTypeName());
            sb.append(",");
        }

        log.setLogMethodParam(sb.toString());
        insertLog(log);
    }

    private void insertLog(Log log) {
        long logId = new SnowFlakeIdUtil(machine.getWorkerId(), machine.getDatacenterId()).genNextId();
        log.setLogId(logId);
        log.setCreateTime(TimeUtil.getLocalDateTime());
        logMapper.insert(log);
    }


}
  1. 使用:

切點表達式


  1. 表達式語法:
execution(<scope> <return-type><fully-qualified-class-name>.*(parameters))
  1. 例子:
    execution(* cn.spy.service.impl.MyServiceImpl.(..))
    解釋:匹配cn.spy.service.impl.MyServiceImpl類下的所有方法
    execution(public void cn.spy.service.impl.MyServiceImpl.
    (..))
    解釋:匹配cn.spy.service.impl.MyServiceImpl類下的public void xx();方法跑慕。
    execution(public void cn.spy.service.impl.MyServiceImpl.*(String,..))
    解釋:匹配cn.spy.service.impl.MyServiceImpl類下第一個參數為String類型,無返回值的所有公共方法。
  2. 通配符:
    ..該通配符匹配方法定義中的任何數量的參數核行。(也可以匹配任意數量的包)
    +該通配符匹配給定類的任何子類牢硅。
    *該通配符匹配任意數量的字符。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末芝雪,一起剝皮案震驚了整個濱河市减余,隨后出現的幾起案子,更是在濱河造成了極大的恐慌惩系,老刑警劉巖位岔,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異堡牡,居然都是意外死亡赃承,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門悴侵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞧剖,“玉大人,你說我怎么就攤上這事可免∽ビ冢” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵浇借,是天一觀的道長捉撮。 經常有香客問我,道長妇垢,這世上最難降的妖魔是什么巾遭? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮闯估,結果婚禮上灼舍,老公的妹妹穿的比我還像新娘。我一直安慰自己涨薪,他們只是感情好骑素,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刚夺,像睡著了一般献丑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侠姑,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天创橄,我揣著相機與錄音,去河邊找鬼莽红。 笑死妥畏,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播咖熟,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼圃酵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了馍管?” 一聲冷哼從身側響起郭赐,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎确沸,沒想到半個月后捌锭,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡罗捎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年观谦,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桨菜。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡豁状,死狀恐怖,靈堂內的尸體忽然破棺而出倒得,到底是詐尸還是另有隱情泻红,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布霞掺,位于F島的核電站谊路,受9級特大地震影響,放射性物質發(fā)生泄漏菩彬。R本人自食惡果不足惜缠劝,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骗灶。 院中可真熱鬧惨恭,春花似錦、人聲如沸矿卑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽母廷。三九已至,卻和暖如春糊肤,著一層夾襖步出監(jiān)牢的瞬間琴昆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工馆揉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留业舍,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像舷暮,于是被迫代替她去往敵國和親态罪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容