[TOC]
# 使用
接下來我們在src目錄下新建一個com.service包,并在該包下創建PersonService接口,其代碼為:
~~~
public interface PersonService {
public void save(String name);
public void update(String name, Integer id);
public String getPersonName(Integer id);
}
~~~
PersonServiceBean.java,其代碼為:
~~~
public class PersonServiceImpl implements PersonService {
@Override
public void save(String name) {
System.out.println("我是save()方法");
}
@Override
public void update(String name, Integer id) {
System.out.println("我是update()方法");
}
@Override
public String getPersonName(Integer id) {
System.out.println("我是getPersonName()方法");
return "xxx";
}
}
~~~
然后,我們就要在com.service包下創建一個切面類——MyInterceptor.java,下面我們來按照以下步驟將其寫出來。
* 首先用`@Aspect`注解聲明整個類是一個切面:
~~~
@Aspect
public class MyInterceptor {
...
}
~~~
* 接著用@Pointcut注解聲明一個切入點
~~~
@Aspect
public class MyInterceptor {
@Pointcut("execution (* com.service.PersonServiceImpl.*(..))")
private void anyMethod() {} // 聲明一個切入點,anyMethod為切入點名稱
...
}
~~~
我們可利用方法簽名來編寫切入點表達式。最典型的切入點表達式是根據方法的簽名來匹配各種方法:
* `execution (* com.service.impl.PersonServiceImpl.*(..))`:匹配PersonServiceImpl類中聲明的所有方法。第一個*代表任意修飾符及任意返回值類型,第二個*代表任意方法,..匹配任意數量任意類型的參數,若目標類與該切面在同一個包中,可以省略包名。
* `execution public * com.service.PersonServiceImpl.*(..)`:匹配PersonServiceImpl類中的所有公有方法。
* `execution public double com.service.PersonServiceImpl.*(..)`:匹配PersonServiceImpl類中返回值類型為double類型的所有公有方法。
* `execution public double com.service.PersonServiceImpl.*(double, ..)`:匹配PersonServiceImpl類中第一個參數為double類型,后面不管有無參數的所有公有方法,并且該方法的返回值類型為double類型。
* `execution public double com.service.PersonServiceImpl.*(double, double)`:匹配PersonServiceImpl類中參數類型為double,double類型的,并且返回值類型也為double類型的所有公有方法。
然后聲明前置通知方法。
前置通知方法在目標方法開始之前執行
~~~
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceImpl.*(..))")
private void anyMethod() {} // 聲明一個切入點,anyMethod為切入點名稱
// 聲明該方法是一個前置通知:在目標方法開始之前執行
@Before("anyMethod()")
public void doAccessCheck() {
System.out.println("前置通知");
}
}
~~~
注意:若是將一個類聲明為一個切面,那么需要把該類放到IOC容器管理。
接下來,我們理應要修改Spring的配置文件——beans.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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<aop:aspectj-autoproxy />
<bean id="myInterceptor" class="com.service.MyInterceptor" />
<bean id="personService" class=" com.service.PersonServiceImpl"></bean>
</beans>
~~~
從上面可看出我們并沒有讓Spring自動掃描和管理Bean。
最后,在src目錄下新建一個junit.test包,并在該包中新建一個單元測試類——SpringAOPTest.java,其代碼為:
~~~
public class SpringAOPTest {
@Test
public void interceptorTest() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) cxt.getBean("personService");
personService.save("xxx");
}
}
~~~
# 細節一
如果我需要得到輸入參數,如在前置通知里面,得到用戶輸入的數據。此時,須將前置通知方法修改為
~~~
@Before("anyMethod() && args(name)")
public void doAccessCheck(String name) {
System.out.println("前置通知:" + name);
}
~~~
`@Before("anyMethod() && args(name)")`匹配的是PersonServiceImpl類中參數為String類型的方法,即save()方法。
# 細節二
如我要獲得PersonServiceImpl類中的getPersonName()方法的返回參數。此時,須將后置通知方法修改為
~~~
@AfterReturning(pointcut="anyMethod()", returning="result")
public void doAfterReturning(String result) {
System.out.println("后置通知:" + result);
}
~~~
`@AfterReturning(pointcut="anyMethod()", returning="result")`匹配的是PersonServiceImpl類中返回值類型為String的方法,并且returning屬性能將返回值傳入進后置通知方法里面。
測試方法修改
~~~
public class SpringAOPTest {
@Test
public void interceptorTest() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) cxt.getBean("personService");
personService.getPersonName(2);
}
}
~~~
# 細節三
在目標方法出現異常時,得到拋出的異常。為了便于試驗,我們須將PersonServiceImpl類的代碼修改為:
~~~
public class PersonServiceImpl implements PersonService {
@Override
public void save(String name) {
throw new RuntimeException("我是異常");
// System.out.println("我是save()方法");
}
@Override
public void update(String name, Integer id) {
System.out.println("我是update()方法");
}
@Override
public String getPersonName(Integer id) {
System.out.println("我是getPersonName()方法");
return "xxx";
}
}
~~~
然后將異常通知方法修改為:
~~~
@AfterThrowing(pointcut="anyMethod()", throwing="e")
public void doAfterThrowing(Exception e) {
System.out.println("異常通知:" + e);
}
~~~
最后,我們還要將SpringAOPTest類的代碼改為:
~~~
public class SpringAOPTest {
@Test
public void interceptorTest() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) cxt.getBean("personService");
personService.save("xxx");
}
}
~~~
打印

- 基礎
- 編譯和安裝
- scanner類(鍵盤錄入)
- Random類(隨機數)
- 數組
- 方法
- 類
- ArrayList集合
- char與int
- eclipse
- IDEA
- 變量與常量
- 常用API
- String,StringBuffer,StringBuilder
- 正則,Date,DateFormat,Calendar
- 包裝類,System,Math,Arrays,BigInteger,BigDecimal
- 集合,迭代器,增強for,泛型
- List,set,判斷集合唯一
- map,Entry,HashMap,Collections
- 異常
- IO
- File
- 遞歸
- 字節流
- 字符流
- IO流分類
- 轉換流
- 緩沖流
- 流的操作規律
- properties
- 序列化流與反序列化流
- 打印流
- commons-IO
- IO流總結
- 多線程
- 線程池
- 線程安全
- 線程同步
- 死鎖
- lock接口
- ThreadLoad
- 等待喚醒機制
- 線程狀態
- jdbc
- DBUtils
- 連接池DBCP
- c3p0連接池
- 網絡編程
- 多線程socket上傳圖片
- 反射
- xml
- 設計模式
- 裝飾器模式
- web service
- tomcat
- Servlet
- response
- request
- session和cookie
- JSP
- EL
- JSTL
- 事務
- 監聽器Listener
- 過濾器Filter
- json
- linux安裝軟件
- 反射詳解
- 類加載器和注解
- 動態代理
- jedis
- Hibernate
- 簡介
- 創建映射文件
- Hibernate核心配置文件
- 事務和增刪改查
- HibernateUtils
- 持久化對象的三種狀態
- 檢索方式
- query
- Criteria
- SQLQuery
- 持久化類
- 主鍵生成策略
- 緩存
- 事務管理
- 關系映射
- 注解
- 優化
- struts2
- 搭建
- 配置詳解
- Action
- 結果跳轉方式
- 訪問ServletAPI方式
- 如何獲得參數
- OGNL表達式
- valueStack 值棧
- Interceptor攔截器
- spring
- 導包
- IOC和DI
- Bean獲取與實例化
- Bean屬性注入
- spring注解
- 注解分層
- junit整合
- aop
- 動態代理實現
- cglib代理實現
- aop名詞
- spring的aop
- aop-xml詳解
- aop-注解詳解
- 代理方式選擇
- jdbcTemplate
- spring事務管理
- 回滾注意
- 事務傳播屬性
- MyBatis
- MyBatis簡介
- 入門程序
- 與jdbc hibernate不同
- 原始Dao開發
- Mapper動態代理方式
- SqlMapConfig.xml配置文件
- 輸入參數pojo包裝類
- resultMap
- 動態sql
- 一對一關聯
- 一對多
- 整合spring
- 逆向工程
- maven
- maven簡介
- 倉庫
- maven目錄結構
- maven常用命令
- 生命周期
- eclipse中maven插件
- 入門程序
- 整合struct
- 依賴范圍
- 添加插件
- idea配置
- jar包沖突
- 分模塊開發
- 構建可執行的jar包(包含依賴jar包)
- springMVC
- 處理流程
- java面試
- java版本升級
- java1-8版本變更
- java9新特性
- 鎖
- java資料
- idea
- jdk版本切換
- log4j
- 入門實例
- 基本使用方法
- Web中使用Log4j
- spring中使用log4j
- java代碼優化