- Spring中通過切入點表達式定義具體切入點,其常用AOP切入點表達式定義
指示符 |
作用 |
bean |
用於匹配指定bean id的的方法執行 |
within
|
用於匹配指定包名下類型內的方法執行 |
@annotation |
用於匹配指定註解修飾的方法執行 |
execution |
用於進行細粒度方法匹配執行具體業務 |
- bean
bean("userServiceImpl")) |
指定一個類 |
bean("*ServiceImpl") |
指定所有的後綴爲serviceImpl的類 |
- within應用於類級別,實現粗粒度的切面表達式定義:
within("aop.service.UserServiceImpl") |
指定類,只能指定一個類 |
within("aop.service.*") |
只包括當前目錄下的類 |
within("aop.service..*") |
指定當前目錄包含所有子目錄中的類 |
- execution方法級別,細粒度的控制:語法:execution(返回值類型 包名.類名.方法名(參數列表))
execution(void aop.service.UserServiceImpl.addUser()) |
匹配方法 |
execution(void aop.service.PersonServiceImpl.addUser(String)) |
方法參數必須爲字符串 |
execution(* aop.service..*.*(..)) |
萬能配置 |
- @annotaion應用於方法級別,實現細粒度的控制:
@annotation(com..anno.RequestLog)) |
指定一個需要實現增強功能的方法 |
- execution 實例:專輯有多首歌,播放每首歌后會顯示這首歌的播放次數。
一.配置類實現
1.接口
package com.qhf.aop.example04;
public interface CD {
void play(int i);
}
2.實現類:空白CD
package com.qhf.aop.example04;
import java.util.List;
public class BlankCD implements CD {
private String title;//專輯名稱
private String artist;//歌手
private List<String> list;//歌曲
public void setTitle(String title) {
this.title = title;
}
public void setArtist(String artist) {
this.artist = artist;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public void play(int i) {
try {
String song = list.get(i);
System.out.print("Playing '" + song + "' by " + artist + "; ");
} catch (Throwable e){
System.out.print("拋異常; ");
throw e;//必須拋出後纔會執行@AfterThrowing
}
}
}
3.配置類,bean實例化返回一個艾薇兒的專輯
package com.qhf.aop.example04;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
@Bean
public BlankCD avrilCD(){
BlankCD b = new BlankCD();
b.setArtist("avril");
b.setTitle("Head above water");
List<String> list = new ArrayList<>();
list.add("Head above water");
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
b.setList(list);
return b;
}
@Bean
public PlayTimes playTimes(){
return new PlayTimes();
}
}
4.切面類
@Pointcut("execution(* com.qhf.aop.example04.BlankCD.play(int)) && args(i)")
public void pointcut(int i){}
參數是int,故play(int)接受一個int 類型參數,&& args(i) 中指定參數名
package com.qhf.aop.example04;
import org.aspectj.lang.annotation.*;
import java.util.HashMap;
import java.util.Map;
@Aspect
public class PlayTimes {
private Map<Integer, Integer> map = new HashMap<>();
@Pointcut("execution(* com.qhf.aop.example04.BlankCD.play(int)) && args(i)")
public void pointcut(int i){
}
/**
* 這首歌播放次數
* @param i
*/
@AfterReturning("pointcut(i)")
public void playTimes(int i){
int count = getPlayCount(i) + 1;
map.put(i, count);
System.out.println("播放次數:" + count);
}
private int getPlayCount(int i){
return map.containsKey(i)? map.get(i): 0;
}
@AfterThrowing("pointcut(i)")
public void noSong(int i){
System.out.println("沒有這首歌喲...");
}
}
5.測試
package com.qhf.aop.example04;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopConfig.class)
public class Test {
@Autowired
private CD avrilCD;
@org.junit.Test
public void test(){
//只有6首歌,0號也有一首歌
avrilCD.play(1);
avrilCD.play(0);
avrilCD.play(1);
avrilCD.play(2);
avrilCD.play(3);
avrilCD.play(4);
avrilCD.play(3);
avrilCD.play(5);
try {
avrilCD.play(6);//沒有這首歌,暫時不知用什麼方法
} catch (Throwable e){
}
avrilCD.play(1);
}
}
6.運行結果
Playing 'one' by avril; 播放次數:1
Playing 'Head above water' by avril; 播放次數:1
Playing 'one' by avril; 播放次數:2
Playing 'two' by avril; 播放次數:1
Playing 'three' by avril; 播放次數:1
Playing 'four' by avril; 播放次數:1
Playing 'three' by avril; 播放次數:2
Playing 'five' by avril; 播放次數:1
拋異常; 沒有這首歌喲...
Playing 'one' by avril; 播放次數:3
二、xml配置實現
1.除了測試類和配置類,其他類全部除去註解
2.配置類
package com.qhf.aop.example05;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource("classpath:aop/example05/aop.xml")
public class AopConfig {
}
3.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 啓動切面代理 -->
<aop:aspectj-autoproxy/>
<!-- 自動裝配bean -->
<bean id="playTimes" class="com.qhf.aop.example05.PlayTimes"/>
<bean id="blankCD" class="com.qhf.aop.example05.BlankCD">
<property name="title" value="Head above water"></property>
<property name="artist" value="avril"></property>
<property name="list">
<list>
<value>Head above water</value>
<value>one</value>
<value>two</value>
<value>three</value>
<value>four</value>
<value>five</value>
</list>
</property>
</bean>
<!-- 聲明切面 -->
<aop:config>
<aop:aspect ref="playTimes">
<aop:pointcut id="point" expression="execution(* com.qhf.aop.example05.BlankCD.play(int)) and args(i)"/>
<aop:after-returning method="playTimes" pointcut-ref="point"/>
<aop:after-throwing method="noSong" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
</beans>
4.測試結果相同