一個目標類對應多個切面的例子
阿新 • • 發佈:2019-01-25
在之前的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>
再執行測試類:
異常: