程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> spring入門(四)【面向切面編程】,spring入門面向切面

spring入門(四)【面向切面編程】,spring入門面向切面

編輯:JAVA綜合教程

spring入門(四)【面向切面編程】,spring入門面向切面


開發過程中很多時候會用到日志、事務等操作,這些操作如果要寫在業務代碼中會相當麻煩,這時就會用到面向切面編程(AOP),AOP作為一種編程思想,和OOP有著不同的側重點,面向對象側重於萬事萬物皆對象,而面向切面編程則側重於事務的一個方面。在面向切面編程過程中有幾個比較重要的概念:切面、切點、連接點、通知,

通知:描述了切面要完成的工作,例如,要向某個方法注入日志功能,這裡的日志功能就是通知;通知分為5種:Before、After、After-returning、After-throwing、Around

切點:定義了通知被應用的地方,如,某個類上的某個方法;例如,在test類的print方法;

切面:橫切關注點被模塊化的類,由通知和切點組成,換句話來說切面定義了要向目標程序注入的全部內容;規定了在目標方法上執行什麼樣的動作;

連接點:程序執行過程中切面可以被插入的一個點,如方法調用、成員變量初始化,在spring中只支持方法調用;

 

面向切面編程有兩種實現方式,一種是預編譯,另一種是動態代理,AspectJ屬於預編譯,springAOP屬於運行期動態代理方式。spring實現了對AspectJ的支持。下面看springAOP和AspectJ的使用方式,

springAOP

這裡使用配置文件的方式,實現springAOP,看配置文件,

    <aop:config>
        <!--聲明一個切面類  可以有多個-->
        <aop:aspect id="myAspect" ref="aspect">
            <!--聲明一個切點-->
            <aop:pointcut id="point1" expression="execution(* com.cn.study.day6.Test.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point1" />
            <aop:around method="around" pointcut-ref="point1"/>
        </aop:aspect>
        
    </aop:config>
    <!--配置切面類-->
    <bean id="aspect" class="com.cn.study.day6.Aspect"></bean>


要配置AOP,在spring中使用了<aop:config>標簽,在這個標簽中可以配置多個切面標簽(<aop:aspect>),每個切面代表了一種橫切關注點,從前面的闡述中可以知道一個切面包含兩部分,一個是切點,另一個是通知,在<aop:aspect>標簽中定義切點(<aop:pointcut>)和通知(aop:before 前置通知),在切點中配置了通知被應用的位置,即匹配Test類的任何方法(execution(* com.cn.study.day6.Test.*(..))),在通知標簽中配置了執行目標方法前通知,切點是point1;下面看具體的切面類,

package com.cn.study.day6;

import org.aspectj.lang.ProceedingJoinPoint;

//切面類
public class Aspect { //前置通知調用的方法 public void before(){ System.out.println("我是前置通知!"); } public Object around(ProceedingJoinPoint jp){ System.out.println("我是環繞通知!"); Object object=null; try { System.out.println("方法執行前"); object = jp.proceed(); System.out.println("方法執行之後"); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } return object; } }

切面類中的方法要和通知中method屬性的方法名字保持一致,下面是目標方法,

package com.cn.study.day6;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class Test {

    public void method1(){
        System.out.println("業務方法!");
    }
}

上面是一個簡單的業務方法,
總結下這個切面類的含義,即在執行com.cn.study.day6.Test類中的任何方法之前都會首先執行com.cn.study.day6.Aspect切面類中的before方法,看打印結果,

我是前置通知!
業務方法!

結果顯示首先執行了切面類中的before方法,然後執行的是目標類中的method1方法。

上面就完成了一個面向切面編程的例子,我們實現的是在方法被調用之前實現橫切,那麼面向切面編程到底有什麼用處呢?我們在最後進行說明,接著看AspectJ

 

AspectJ

AspectJ是AOP的另一種實現,要使用AspectJ必須打開自動代理,如下

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

這是對AspectJ的自動代理,然後就可以使用AspectJ了,看下面的切面類

package com.cn.study.day7;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AspectTest {
    //前置通知調用的方法  通知
    @Before("pointCut1()")
    public void before(){
        
        System.out.println("我是前置通知!");
        
    }
    //切點
    @Pointcut("execution(* com.cn.study.day7.Test.*(..))")
    public void pointCut1(){
        
    }

}

由於加了@AspectJ的類無法被自動識別,所以需要加載@Component注解,有了這兩個注解之後,此類便是一個切面類了,在切面類裡可以聲明切點和通知,我們定義了一個pointCut1的切點,此方法的返回值必須是void,此切點對com.cn.study.day7.Test下的所有方法有效,接著使用@Before定義了一個前置通知,且使用的切點為pointCut1(),打印結果如下,

我是前置通知!
業務方法!

上面便完成了使用AspectJ的切面編程;另,在定義通知的之後也可以直接使用表達式(execution(* com.cn.study.day7.Test.*(..)))而不必引用某個切點,引用某個切點的好處是,在定義了切點之後可以復用。

綜上,是兩種實現AOP的配置,AOP的使用場景是在不破壞原有代碼的基礎上,增加新的功能,比如日志、事務控制,使用AOP可以很好地減少代碼的侵入,在原有代碼不變的基礎上輕松實現日志、事務控制、權限控制等。這兩種方式在實際開發過程當中使用的都很廣泛,具體使用哪種方式可根據自己的情況而定。

有不足之處,歡迎指出!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved