spring aop的基於xml以及註解的配置
阿新 • • 發佈:2018-11-28
AOP概述
springAOP:面向切面程式設計。是面向物件程式設計的一種有效補充。面向物件程式設計的三大要素是繼承、多型和封裝。即在類設計時,要求讓不同的類設計不同的方法。但是這種模式下,也會產生一些弊端。比如增加了程式碼的重複性。比如我們想在類中增加日誌的記錄,如果讓每個類都做日記的功能,程式碼就重複了,一種方法是將日誌的程式碼提取出來,設計成一個獨立的類,讓需要日記記錄的類呼叫這個類,但是這樣就增加了程式碼的耦合性。為了能夠靈活的配置類的日誌功能,需要動態的將日誌程式碼切入到我們指定的需要日誌記錄功能的類中,這種思想就是面向切面的思想。
我們稱可以被切入的類的方法為連線點,而真正被切入的方法稱為切點(切點是連線點的一部分,並不是所有的連線點都需要被切入)。而切入的方法就是通知,其定義了切面是什麼以及何時使用,主要是前置、後置、環繞、返回、及異常通知。
切面程式設計可以形象的理解為:普通的類就是一個個橫向的面,而我們的aop則是縱向的向物件切入特定的程式碼。
基於aspect的aop實現
基於xml形式
1、首先定義目標介面和目標類
public interface UserService {
void insert(String name,String password);
void update(String name,String password);
int query(String name,String password);
void delete(String name,String password);
}
public class UserServiceImpl implements UserService {
/* (non-Javadoc)
* @see com.test.aop.dongtaidaili.UserService#insert()
*/
@Override
public void insert(String name,String password) {
// TODO Auto-generated method stub
System.out.println("插入");
}
/* (non-Javadoc)
* @see com.test.aop.dongtaidaili.UserService#update()
*/
@Override
public void update(String name,String password) {
// TODO Auto-generated method stub
System.out.println("更新");
}
/* (non-Javadoc)
* @see com.test.aop.dongtaidaili.UserService#query()
*/
@Override
public int query(String name,String password) {
// TODO Auto-generated method stub
System.out.println("查詢");
return 1;
}
/* (non-Javadoc)
* @see com.test.aop.dongtaidaili.UserService#delete()
*/
@Override
public void delete(String name,String password) {
// TODO Auto-generated method stub
System.out.println("刪除");
}
}
定義切面(通知)
public class MyAdvice {
public void before(JoinPoint joinPoint){
for (int i = 0; i < joinPoint.getArgs().length; i++) {
System.out.println("獲取引數--》"+joinPoint.getArgs()[i].toString());
}
}
public void after(){
System.out.println("後置通知");
}
//環繞通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("這是環繞通知之前的部分!!");
if (pjp.getArgs().length>=2) {
if (pjp.getArgs()[0].equals("andy")&&pjp.getArgs()[1].equals("111")) {
Object proceed = pjp.proceed();//呼叫目標方法
System.out.println("計算結果-->"+proceed.toString());
return proceed;
}else {
System.out.println("使用者名稱和密碼不正確,不執行目標類");
return null;
}
}else { //如果引數小於2,那就直接執行環繞通知
Object proceed = pjp.proceed();//呼叫目標方法
return proceed;
}
}
//異常通知
public void afterException(){
System.out.println("出事啦!出現異常了!!");
}
}
最後看xml的配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 資料庫連線池 -->
<!-- <context:component-scan base-package="com.test.aop*"></context:component-scan> -->
<bean id="userService" class="com.test.aop.spring.UserServiceImpl"></bean>
<bean id="myAdvice" class="com.test.aop.spring.MyAdvice"></bean>
<aop:config>
<!-- 配置切入點 -->
<aop:pointcut expression="execution(* com.test.aop.spring.UserServiceImpl.*(..))" id="pointcut1"/>
<!-- 配置通知-->
<aop:aspect ref="myAdvice">
<aop:before method="before" pointcut-ref="pointcut1"/>
<aop:around method="around" pointcut-ref="pointcut1"/>
<aop:after-throwing method="afterException" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
看測試,當用戶名和密碼正確時,執行目標類
@org.junit.Test
public void test(){
userService.query("andy","111");
}
}
結果是
獲取引數--》andy
獲取引數--》111
這是環繞通知之前的部分!!
查詢
計算結果-->1
當用戶名和密碼不正確時,
@org.junit.Test
public void test(){
userService.query("andy","222");
}
}
結果是:
獲取引數--》andy
獲取引數--》222
這是環繞通知之前的部分!!
使用者名稱和密碼不正確,不執行目標類
達到效果
基於註解的方式
首先,定義切點和通知。(切點與基於xml配置的一樣,不重複寫了)
@Aspect
public class MyAdvice1 {
//配置切入點
@Pointcut("execution(* com.test.aop.anno.UserService1.*(..))")
public void pointcut(){
}
@Before("pointcut()")
public void before(JoinPoint joinPoint){
for (int i = 0; i < joinPoint.getArgs().length; i++) {
System.out.println("獲取引數--》"+joinPoint.getArgs()[i].toString());
}
}
@After("pointcut()")
public void after(){
System.out.println("後置通知");
}
//環繞通知
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("這是環繞通知之前的部分!!");
if (pjp.getArgs().length>=2) {
if (pjp.getArgs()[0].equals("andy")&&pjp.getArgs()[1].equals("111")) {
Object proceed = pjp.proceed();//呼叫目標方法
System.out.println("計算結果-->"+proceed.toString());
return proceed;
}else {
System.out.println("使用者名稱和密碼不正確,不執行目標類");
return null;
}
}else {
Object proceed = pjp.proceed();//呼叫目標方法
return proceed;
}
}
//異常通知
@AfterThrowing("pointcut()")
public void afterException(){
System.out.println("出事啦!出現異常了!!");
}
}
然後,在xml中啟動aspect自動代理,以及宣告切點和通知bean
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="userService1" class="com.test.aop.anno.UserServiceImpl1"></bean>
<bean id="myAdvice1" class="com.test.aop.anno.MyAdvice1"></bean>