[TOC]
# 定義通知
準備的類還是用UserServiceImpl
~~~
package aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
//通知類
//表示該類是一個通知類
@Aspect
public class MyAdvice {
@Pointcut("execution(* service.*ServiceImpl.*(..))")
public void pc() {
}
// 前置通知
@Before("MyAdvice.pc()")
public void before(JoinPoint jp) {
// 使用前置通知可以完成日志記錄,權限控制
System.out.println("攔截的目標類: " + jp.getSignature().getDeclaringTypeName());
System.out.println("攔截的方法名稱: " + jp.getSignature().getName());
System.out.println("這是前置通知");
}
// 后置通知(如果出現異常不會調用)
@AfterReturning("execution(* service.*ServiceImpl.*(..))")
public void afterReturning(JoinPoint jp, Object val) {
// 第二個參數val它可以獲取目標方法的返回值
// 注意:需要在配置文件中配置
// returning="val"
System.out.println("這是后置通知(如果出現異常不會調用)");
}
// 環繞通知
@Around("execution(* service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 可以完成日志操作,權限操作,性能監控,事務管理
System.out.println("這是環繞通知之前的部分");
// 調用目標方法
Object proceed = pjp.proceed();
System.out.println("這是環繞通知之后的部分");
return proceed;
}
// 異常通知
@AfterThrowing("execution(* service.*ServiceImpl.*(..))")
public void afterException() {
System.out.println("出現異常了");
}
// 后置通知(如果出現異常也會調用)
@After("execution(* service.*ServiceImpl.*(..))")
public void after(JoinPoint jp) {
System.out.println(jp.getSignature().getName());
System.out.println("這是后置通知(如果出現異常也會調用)");
}
}
~~~
# 導入約束



# 進行配置
~~~
<aop:config>來聲明要對aop進行配置
<aop:pointcut>它是用于聲明切點(簡單說就是對哪些方法進行攔截)
<aop:advisor> 定義傳統的aop的切面,傳統的aop切面它只能包含一個切點與一個增強
<aop:aspect>定義aspectj框架的切面.,它可以包含多個切點與多個通知
~~~
~~~
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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-4.2.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(約束)命名空間 -->
<!-- 1.配置目標對象 -->
<bean name="userService" class="service.UserServiceImpl"></bean>
<!-- 2.配置通知對象 -->
<bean name="myAdvice" class="aspect.MyAdvice"></bean>
<!-- 3.配置將通知織入目標對象 -->
<aop:config>
<!-- 配置切入點
public void service.UserServiceImpl.save()
void service.UserServiceImpl.save()
* service.UserServiceImpl.save()
* service.UserServiceImpl.*()
* service.UserServiceImpl.*(..)
* service.*ServiceImpl.*(..)
* service..*ServiceImpl.*(..) //還會找子包
-->
<aop:pointcut expression="execution(* service.*ServiceImpl.*(..))" id="pc"/>
<aop:aspect ref="myAdvice">
<!-- 指定名為before方法為前置通知 -->
<aop:before method="before" pointcut-ref="pc" />
<!-- 后置通知(如果出現異常不會調用) -->
<aop:after-returning method="afterReturning" pointcut-ref="pc" returning="val" />
<!-- 環繞通知 -->
<aop:around method="around" pointcut-ref="pc" />
<!-- 異常攔截通知 -->
<aop:after-throwing method="afterException" pointcut-ref="pc" />
<!-- 后置 -->
<aop:after method="after" pointcut-ref="pc" />
</aop:aspect>
</aop:config>
</beans>
~~~
~~~
關于execution語法常用:
1. execution(public * *()) 所有的public的方法
2. execution(* cn.itheima.aop.*(..)) 所有的aop包下的所有類的方法(不包含子包)
3. execution(* cn.itheima.aop..*(..)) 所有的aop包及其子包下的所有類的方法
4. execution(* cn.itheima.aop.IOrderService.*(..)) IOrderService接口中定義的所有方法
5. execution(* cn.itheima.aop.IOrderService+.*(..)) 匹配實現特定接口所有類的方法
6. execution(* save*(..)) 區配所有的以save開頭的方法
~~~
# 測試
~~~
//幫我們創建容器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定創建容器時使用那個配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
@Resource(name = "userService")
private UserService us;
@Test
public void fun1() {
us.save();
}
}
~~~
# 使用注解
需要改下配置文件
~~~
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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-4.2.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(約束)命名空間 -->
<!-- 1.配置目標對象 -->
<bean name="userService" class="service.UserServiceImpl"></bean>
<!-- 2.配置通知對象 -->
<bean name="myAdvice" class="aspect.MyAdvice"></bean>
<!-- 3.開啟使用注解完成織入,開啟aspectJ注解自動代理功能 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
~~~
然后MyAdvice類
~~~
package aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//通知類
//表示該類是一個通知類
@Aspect
public class MyAdvice {
// 前置通知
@Before("execution(* service.*ServiceImpl.*(..))")
public void before() {
System.out.println("這是前置通知");
}
// 后置通知(如果出現異常不會調用)
@AfterReturning("execution(* service.*ServiceImpl.*(..))")
public void afterReturning() {
System.out.println("這是后置通知(如果出現異常不會調用)");
}
// 環繞通知
@Around("execution(* service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
/**
* 環繞通知內部一定要確保執行該方法,如果不執行該方法,業務bean中被攔截的方法就不會被執行。
* 當執行該方法,如果后面還有切面的話,它的執行順序應該是這樣的:先執行后面的切面,如果后面沒有切面了,
* 再執行最終的目標對象的業務方法。若不執行該方法,則后面的切面,業務bean的方法都不會被執行。
*/
System.out.println("這是環繞通知之前的部分");
// 調用目標方法
Object proceed = pjp.proceed();
System.out.println("這是環繞通知之后的部分");
return proceed;
}
// 異常通知
@AfterThrowing("execution(* service.*ServiceImpl.*(..))")
public void afterException() {
System.out.println("出現異常了");
}
// 后置通知(如果出現異常也會調用)
@After("execution(* service.*ServiceImpl.*(..))")
public void after() {
System.out.println("這是后置通知(如果出現異常也會調用)");
}
}
~~~
其他一樣
我們可以再把一些東西抽出來
~~~
@Pointcut("execution(* service.*ServiceImpl.*(..))")
public void pc() {
}
// 前置通知
@Before("MyAdvice.pc()")
public void before() {
System.out.println("這是前置通知");
}
~~~
使用@Pointcut注解定義切點
在每一個通知中定義切點,工作量大,不方便維護,我們可以使用@Pointcut來聲明切點
切點允許邏輯運算例如`mypointcut()||mypointcut1`

- 基礎
- 編譯和安裝
- 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代碼優化