Spring使用註解的方式實現AOP的開發——Spring AOP(七)
阿新 • • 發佈:2018-11-04
上一章我們已經學過使用XML的方式實現AOP:
https://blog.csdn.net/qq_34598667/article/details/83502426
本章我們學習一下使用註解的方式實現AOP
Spring使用註解的方式實現AOP的開發
本章所需知識點
1、開啟aop註解的自動代理
< aop:aspectj-autoproxy/>
2、 AspectJ的AOP的註解:
- @Aspect:定義切面類的註解
- 通知型別:
@Before:前置通知
@AfterReturing:後置通知
@Around:環繞通知
@After:最終通知
@AfterThrowing:異常丟擲通知. - @Pointcut:定義切入點的註解
3、切入點語法表示式(與xml方式一樣)
語法:execution(表示式)
表示式語法:[方法訪問修飾符] 方法返回值包名.類名.方法名(方法的引數)
例1:
execution (* com.oak.service.impl.UserServiceImpl.*(…)) :匹配UserServiceImpl類中宣告的所有方法。
第一個 * :代表任意修飾符及任意返回值型別
第二個 * :代表任意方法,
… :匹配任意數量任意型別的引數,若目標類與該切面在同一個包中,可以省略包名。
例2:execution public double cn.itcast.service.impl.PersonServiceImpl.*(…):匹配PersonServiceImpl類中返回值型別為double型別的所有公有方法。
實現案例
本章案例基於上一章使用xml的方式實現AOP的專案上繼續完成:
1)編寫目標類
建立介面InfoService
public interface InfoService {
void save();
void update();
void delete();
void find();
}
建立實現類InfoServiceImpl
public class InfoServiceImpl implements InfoService{
@Override
public void save() {
System.out.println ("I am the method for save ");
}
@Override
public void update() {
System.out.println("I am the method for update ");
}
@Override
public void delete() {
System.out.println("I am the method for delete ");
}
@Override
public void find() {
System.out.println("I am the method for find ");
}
}
2)配置目標類
<!--配置目標類 -->
<bean id="infoService" class="com.oak.service.InfoServiceImpl"></bean>
3)開啟aop自動代理
<!--配置目標類 -->
<bean id="infoService" class="com.oak.service.InfoServiceImpl"></bean>
<!-- 開啟aop的自動代理 -->
<aop:aspectj-autoproxy/>
4)編寫切面類MyAspectAnno
宣告切入點和通知方法
@Aspect
public class MyAspectAnno {
//宣告一個切入點,anyMethod為切入點名稱,指定切入點,哪些方法需要通知
@Pointcut("execution (* com.oak.service.InfoService.*(..))")
private void anyMethod(){}
//宣告該方法是一個前置通知:在目標方法開始之前執行
@Before("anyMethod()")
public void doBeforeCheck() {
System.out.println("前置通知");
}
}
5)配置切面類
<!--配置切面類-->
<bean id="myAspectAnno" class="com.oak.aop.MyAspectAnno"></bean>
6)測試
在測試類中編寫測試方法
@Test
public void aopAnnoTest(){
ApplicationContext cxt =
new ClassPathXmlApplicationContext
("applicationContext.xml");
InfoService infoService=cxt.getBean("infoService",InfoService.class);
infoService.save();
}
測試結果是:
前置通知
I am the method for save
7)其他通知
修改切面類,使用註解加上其他通知
@Aspect
public class MyAspectAnno {
//宣告一個切入點,anyMethod為切入點名稱,指定切入點,哪些方法需要通知
@Pointcut("execution (* com.oak.service.InfoService.*(..))")
private void anyMethod(){}
//宣告該方法是一個前置通知:在目標方法開始之前執行
@Before("anyMethod()")
public void doBeforeCheck() {
System.out.println("前置通知");
}
@AfterReturning("anyMethod()")
public void doAfterReturning() {
System.out.println("後置通知");
}
@After("anyMethod()")
public void doAfter() {
System.out.println("最終通知");
}
@AfterThrowing("anyMethod()")
public void doAfterThrowing() {
System.out.println("異常通知");
}
@Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
/**
* 環繞通知內部一定要確保執行該方法,如果不執行該方法,業務bean中被攔截的方法就不會被執行。
* 當執行該方法,如果後面還有切面的話,它的執行順序應該是這樣的:先執行後面的切面,如果後面沒有切面了,
* 再執行最終的目標物件的業務方法。若不執行該方法,則後面的切面,業務bean的方法都不會被執行。
*/
// if () { // 判斷使用者是否有許可權,
System.out.println("進入方法");
Object result = pjp.proceed();
System.out.println("退出方法");
// }
return result;
}
}
注意:環繞通知內部一定要確保執行proceed()該方法,如果不執行該方法,業務bean中被攔截的方法就不會被執行。當執行該方法,如果後面還有切面的話,它的執行順序應該是這樣的:先執行後面的切面,如果後面沒有切面了,再執行最終的目標物件的業務方法。若不執行該方法,則後面的切面,業務bean的方法都不會被執行。
執行測試:
進入方法
前置通知
I am the method for save
退出方法
最終通知
後置通知