Spring中AOP開發
阿新 • • 發佈:2018-11-20
Aop思想
- servlet技術中的filter過濾器技術
- struts2中的interceptor技術
- 動態代理
spring-aop開發概念
spring封裝了代理技術來體現aop思想.
spring可以對所有類進行代理.
spring為了能夠對所有類進行代理.封裝了兩種代理技術
動態代理
侷限性:被帶代理物件必須實現至少一個介面.動態代理技術是基於介面的代理技術
沒有實現介面那麼無法被動態代理.
CGLib代理
屬於繼承代理.該技術生成的代理類是被代理類的子類. 幾乎所有類都可以被CGLIb代理.處了被final修飾的類.
有關aop的名詞解釋
連線點(join point): 所有可以被增強(代理)的方法
切點(point cut):即將(需要)或已經被增強的方法
通知(advice):對切點需要增強的程式碼
目標物件(target):被代理的物件
代理物件(proxy):對目標物件的切點應用通知後生成的物件
織入(weaver)動詞:將通知應用到切點的過程,或者說生成代理物件的過程
切面:(aspect|advisor)組合詞:切點+通知 稱之為切面
aop在spring中的配置
使用xml配置檔案開發
- 導包
4+2包+spring-aop包+spring-aspects包 2個在spring輔助包中:aop聯盟包+aspectj-weaver包
- 目標物件
- 通知(對切點需要增強的程式碼,一個類)
前置通知 通知程式碼,在目標方法執行前呼叫
環繞通知 通知程式碼,在目標方法執行前和執行後都呼叫
後置通知 通知程式碼,在目標方法執行後呼叫. 切點方法丟擲異常,通知不執行
後置通知 通知程式碼,在目標方法執行後呼叫. 切點方法丟擲異常,通知仍然執行
異常通知 通知程式碼,在目標方法丟擲異常後才會執行.
- 配置
1.匯入aop約束,字首為aop
2.註冊目標物件,註冊通知物件
3.在xml中配置
<?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: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 "> <!-- 1.配置目標物件 --> <bean name="userService" class="cn.xiaos.service.UserServiceImpl" ></bean> <!-- 2.配置通知物件 --> <bean name="myAdvice" class="cn.xiaos.advice.MyAdvice" ></bean> <!-- 3.配置切面 切點+通知 --> <!-- 3.1 書寫切點表示式,aspectJ切點表示式 格式 : execution(表示式) public void cn.itcast.service.UserServiceImpl.save() void cn.itcast.service.UserServiceImpl.save() 同上 * cn.itcast.service.UserServiceImpl.save() 方法返回值任意 * cn.itcast.service.*ServiceImpl.save() 包中所有以ServiceImpl結尾的類 * cn.itcast.service.*ServiceImpl.*() 方法名任意 * cn.itcast.service.*ServiceImpl.*(..) 沒有或多個任意引數 * cn.itcast.service..*ServiceImpl.*(..) 當前包以及後代包 --> <aop:config> <!-- aop:pointcut : 配置切點(需要被增強的方法) expression:表示式 id:為表示式指定名稱,方便後續引用 --> <aop:pointcut expression="execution(* cn.xiaos.service.*ServiceImpl.*(..))" id="myPC"/> <!-- 配置通知+切點 => 切面 ref:哪個物件是通知類 --> <aop:aspect ref="myAdvice" > <!-- 前置通知 method=>方法名 pointcut-ref=>切點名稱 --> <aop:before method="before" pointcut-ref="myPC" /> <!-- 環繞通知 --> <aop:around method="around" pointcut-ref="myPC" /> <!-- 後置通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPC" /> <!-- 後置通知 --> <aop:after method="after" pointcut-ref="myPC" /> <!-- 異常通知 --> <aop:after-throwing method="afterThrowing" pointcut-ref="myPC" /> </aop:aspect> </aop:config> </beans>
使用註解方式配置
1.導包(同上),2.目標檔案編寫(同上)3.註冊目標物件,註冊通知物件
3.開啟aop註解配置事務開關
<aop:aspectj-autoproxy> </aop:aspectj-autoproxy>
4.在通知類中使用註解配置切面
package cn.xiaos.advice;
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;
// 5種通知
// 前置通知 通知程式碼,在目標方法執行前呼叫
// 環繞通知 通知程式碼,在目標方法執行前和執行後都呼叫
// 後置通知 通知程式碼,在目標方法執行後呼叫. 切點方法丟擲異常,通知不執行
// 後置通知 通知程式碼,在目標方法執行後呼叫. 切點方法丟擲異常,通知仍然執行
// 異常通知 通知程式碼,在目標方法丟擲異常後才會執行.
//通知類
//@Aspect => 標識當前類用於配置切面
@Aspect
public class MyAdvice {
@Pointcut("execution(* cn.itcast.service.*ServiceImpl.*(..))")
public void myPC(){}
// 前置通知
@Before("MyAdvice.myPC()")
public void before() {
System.out.println("我是前置通知!");
}
// 環繞通知
@Around("MyAdvice.myPC()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("我是環繞通知前半部分,我在切點方法執行前執行!");
// 手動呼叫切點方法執行
Object obj = pjp.proceed(); // 執行切點方法
System.out.println("我是環繞通知後半部分,我在切點方法執行後執行!");
return obj;
}
// 後置通知 => 出現異常,就不執行
@AfterReturning("MyAdvice.myPC()")
public void afterReturning() {
System.out.println("我是後置通知,出現異常不執行!");
}
// 後置通知 => 出現異常,仍然執行
@After("MyAdvice.myPC()")
public void after() {
System.out.println("我是後置通知,出現異常仍然執行!");
}
// 異常通知
@AfterThrowing("MyAdvice.myPC()")
public void afterThrowing() {
System.out.println("我是異常通知,丟擲異常後執行!");
}
}