1. 程式人生 > >一個目標類對應多個切面的例子

一個目標類對應多個切面的例子

在之前的cglib代理原理中(至於cglib和jdk代理的區別,看之前的博文),我們涉及到了多個切面,但是那時候說的切面,還不算真正意義上的切面(沒有在spring配置檔案中配置)。現在我修改一個那個例子.

需求:

我們仍然查詢某一個人的薪水

需求分析:

我們直接通過目標類來查詢某個人的薪水,但是在我們通過呼叫目標方法的時候,有各種通知在運作,就像攔截器一樣,如果沒有相應的許可權的話,就不給查詢。

通知的分析:

在以前的例子中,我們用到了3個切面,分別是privilege(許可權),security(安全性框架),logger(日誌),當時由於我們還沒有學通知的概念,所以只是呼叫了一下其中的方法而已,現在我們要區分一下它們對應的方法分別屬於什麼通知。

日誌切面和安全性框架切面對於使用者的許可權沒有要求,只要你傳送了這個請求,就要經過相應的通知,所以日誌和安全性框架屬於前置通知。

許可權切面是需要在經過了前置通知之後,然後再判斷是否滿足相應的條件來決定是否讓客戶端執行目標方法,所以許可權切面的方法屬於環繞通知。

程式碼實現:

以下是切面的定義:

//日誌切面
public class Logger {
    public void logging(){
        System.out.println("logging");
    }
}   


//安全性框架切面:
public class Security {
    public
void security(){ System.out.println("security"); } } //許可權切面 public class Privilege { //設定一個變數,並且設定其getter&setter方法,這樣就可以在配置檔案中賦值 private String access; /** * 判斷使用者是否為admin,如果不是,就不給查詢 * @param joinPoint * @throws Throwable */ public void isAccess(ProceedingJoinPoint joinPoint) throws
Throwable{ if("admin".equals(access)){ //允許客戶端呼叫目標方法 joinPoint.proceed(); }else{ //丟擲沒有相應許可權的異常 throw new RuntimeException("you have no privilege to pull this request"); } } //getter&setter方法,如果沒有這個方法,會報錯 public String getAccess() { return access; } public void setAccess(String access) { this.access = access; } } //下面是目標類: public class SalaryManager { public void showSalary(){ System.out.println("show salary"); } }

以下是配置檔案的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

     <!-- 
        把要用到的切面以及目標類配置到配置檔案中
      -->      

    <bean id="logger" class="cn.ansel.oneTarget2ManyAspects.Logger"></bean>
    <bean id="security" class="cn.ansel.oneTarget2ManyAspects.Security"></bean>
    <!-- 
        為privilege類中的access屬性賦值
     -->
    <bean id="privilege" class="cn.ansel.oneTarget2ManyAspects.Privilege">
        <property name="access" value=""admin""></property>
    </bean>


    <bean id="salaryManager" class="cn.ansel.oneTarget2ManyAspects.SalaryManager"></bean>

    <aop:config>
        <!-- 
            設定切入點表示式
         -->
        <aop:pointcut expression="execution(* cn.ansel.oneTarget2ManyAspects.SalaryManager.*(..))" id="perform"/>
        <!-- 
            有幾個切面就要定義幾個aop:aspect 並且把ref的值設定好
         -->
        <aop:aspect ref="logger">
            <aop:before method="logging" pointcut-ref="perform"/>
        </aop:aspect>

        <aop:aspect ref="security">
            <aop:before method="security" pointcut-ref="perform"/>
        </aop:aspect>
        <!-- 
            在這裡設定好環繞通知,
         -->
        <aop:aspect ref="privilege">
            <aop:around method="isAccess" pointcut-ref="perform"/>
        </aop:aspect>
    </aop:config>
</beans>
//以下是測試類的程式碼:
public class testOne2Many {
    @Test
    public void test(){
        //開啟spring容器
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("cn/ansel/oneTarget2ManyAspects/applicationContext.xml");
        //使用cglib代理得到目標類的代理物件
        SalaryManager cglibProxy=(SalaryManager) applicationContext.getBean("salaryManager");
        //呼叫目標方法
        cglibProxy.showSalary();
    }
}

執行結果:
這裡寫圖片描述
當我們把配置檔案中access的值改成其他值的時候

<property name="access" value="asd"></property>

再執行測試類:
這裡寫圖片描述
異常:
這裡寫圖片描述