Spring的使用(二):AOP

簡介

    Aspect Oriented Programming(AOP)稱爲面向切面編程,在程序開發中主要用來解決一些系統層面上的問題,如日誌,事務,權限等等

相關概念

  1. 滿足OCP開閉原則:對程序擴展打開,對程序修改關閉
  2. Aspect(切面):通常是一個類,在切面中定義通知和切入點
  3. JointPoint(連接點):需要攔截的點(方法類型)
  4. PointCut(切入點):指定連接點的規則,規定連接點連接位置以及對連接點進行篩選
  5. Advice(通知):決定增強業務的內容,有before(前置),after(後置),afterReturning(最終),afterThrowing(異常),around(環繞)

搭建

  1. 依賴包 spring-aop
  2. AspectJ組件
    a.aopalliance (aop聯盟規則)
    b.spring-aspects(spring的aspectj集成包)
    c.aspectj.weaver(AspectJ織入包)

連接點

自動記錄對應方法的信息
方法名:jointPoint.getSignature().getName()
目標對象:jointPoint.getTarget().getClass().getName()
代理對象:jointPoint.getThis().getClass().getName()
方法的返回值(後置通知,環繞通知,最終通知) 要在配置文件中配置返回值綁定到後置通知的參數上

使用

applicationContext.xml

<!--業務層-->
<bean id="userService" class="com.service.UserServiceImpl"></bean>
<bean id="proService" class="com.service.ProServiceImpl"></bean>

<!--切面-->
<bean id="myAspect" class="com.aop.MyAspect"></bean>

<!--配置切入點和切面-->
<aop:config>
    <aop:pointcut id="xxx1" expression="bean(proService)"/>
    <!--1.規定切面  -->
    <aop:aspect ref="myAspect">
        <!--2.切入點 切入的規則-->
        <aop:pointcut id="xxx" expression="bean(*Service)"/>
        <!--3.配置通知的時間點-->
        <!--
            1.前置通知before 在進入連接點之前執行
            2.後置通知AfterReturning 連接點執行之後通知再執行
            3.環繞通知Around 連接點執行的整個過程
            4.異常通知AfterThrowing  在連接點拋出異常之後
            5.最終通知After 無論方法是否異常都一定會執行
        -->
       <aop:before method="beforeLogin" pointcut-ref="xxx" ></aop:before>
       <aop:after-returning method="afterRetuturningLogin" pointcut-ref="xxx" returning="returnVal"></aop:after-returning>
       <aop:around method="around" pointcut-ref="xxx"></aop:around>
       <aop:after-throwing method="afterThrowing" pointcut-ref="xxx" throwing="ex"></aop:after-throwing>
       <aop:after method="after" pointcut="bean(*Service)" ></aop:after>
    </aop:aspect>
</aop:config>

MyAspect.java(切面類)

public class MyAspect {
    //前置通知
    public void beforeLogin(JoinPoint jointPoint){
        //方法名
        System.out.println("=============開始進入前置通知===============");
        System.out.println("攔截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目標對象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理對象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("當前方法的參數" + Arrays.toString(jointPoint.getArgs()));
        System.out.println("進入了方法前的時間是" + CommmonUtil.getTime());
        System.out.println("=============前置通知結束===============");
    }

    //後置通知
    public void afterRetuturningLogin(JoinPoint jointPoint,Object returnVal){
        System.out.println("=============開始進入後置通知===============");
        System.out.println("攔截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目標對象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理對象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("當前方法的返回值是" + returnVal);
        System.out.println("出方法的時間是" + CommmonUtil.getTime());
        System.out.println("=============後置通知結束===============");
    }
	//環繞通知(本質就是代理原來的方法)
    public Object around(ProceedingJoinPoint jointPoint) throws Throwable {
        System.out.println("=============開始進入環繞通知===============");
        System.out.println("攔截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目標對象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理對象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("當前方法的參數" + Arrays.toString(jointPoint.getArgs()));
        System.out.println("進入了方法前的時間是" + CommmonUtil.getTime());
        Object returnVal = jointPoint.proceed();
        System.out.println("當前方法的返回值是" + returnVal);
        System.out.println("出方法的時間是" + CommmonUtil.getTime());
        System.out.println("=============環繞通知結束===============");
        return returnVal;
    }

    //異常通知
    public void afterThrowing(JoinPoint jointPoint,Throwable ex){
        System.out.println("=============開始進入異常通知===============");
        System.out.println("攔截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目標對象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理對象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("異常信息爲=====" + ex.getMessage());
        System.out.println("異常時間是" + CommmonUtil.getTime());
        System.out.println("=============異常通知結束===============");
    }

    //最終通知
    public void after(JoinPoint jointPoint){
        System.out.println("=============開始進入最終通知===============");
        System.out.println("攔截的方法名是===" + jointPoint.getSignature().getName());
        System.out.println("目標對象是==="+jointPoint.getTarget().getClass().getName());
        System.out.println("代理對象是====" + jointPoint.getThis().getClass().getName());
        System.out.println("最終的時間是" + CommmonUtil.getTime());
        System.out.println("=============最終結束===============");
    }
}

調用*Service實例中的方法則會完成AOP代理運行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章