Spring Aop
實現
——
Annotation
方式(註解式)
一、spring
依賴庫
* SPRING_HOME/dist/spring.jar
* SPRING_HOME/lib/jakarta-commons/commons-logging.jar
* SPRING_HOME/lib/log4j/log4j-1.2.14.jar
* SPRING_HOME/lib/
aspect
j/*.jar
二、編寫切面
aspect
類
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* 定義切面
* @author
*/
@Aspect
public class CheckAspect {
/**
* 定義切入點(Pointcut),Pointcut的名稱就是allSaveMethod, 此方法不能有參數和返回值,僅是個標識。
* Pointcut的內容——"execution(*, save*(..))",是個表達式,描述哪些對象的哪些方法(訂閱Joinpoint)
*
*/
@Pointcut("execution(* save*(..)) || execution(* del*(..))")
private void allSaveMethod(){};
/*
* 定義通知advice(before型),標識在哪個切入點(allSaveMethod),織入(weaver)此方法
*/
@Before("allSaveMethod()")
public void checkUser(){
System.out.println("=======CheckAspect.checkUser()===========");
}
}
軟件工程師速成系列之Spring AOP
Spring Aop的思...AOP的基本概念
測試服務類:
public class UserManagerImpl implements IUserManager {
public void delUser(int id) {
System.out.println("=====UserManagerImpl.delUser()===========");
}
public String findUser(int id) {
System.out.println("=====UserManagerImpl.findUser()===========");
return null;
}
public void saveUser(String username, String password) {
System.out.println("=====UserManagerImpl.saveUser()===========");
}
public void updateUser(int id) {
System.out.println("=====UserManagerImpl.updateUser()===========");
}
}
三、
applicationContext.xml
中開啓aop,配置相關切面aspect類
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/txxsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >
<!-- 啓用aop -->
<aop:aspectj-autoproxy/>
<!--配置aspect-->
<bean id="checkAspect" class="com.CheckAspect" />
<bean id="userManager" class="com.manager.impl.UserManagerImpl" />
</beans>
四、測試用例:
public void testAspect(){
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserManager userManager = (IUserManager) factory.getBean("userManager");//生成的代理類proxy
userManager.saveUser("cat", "123");
userManager.delUser(1);userManager.updateUser(1);
//沒有調用切面advice,因爲方法update與之不匹配。
}
執行結果:
=======CheckAspect.checkUser()===========
=====UserManagerImpl.saveUser()===========
=======CheckAspect.checkUser()===========
=====UserManagerImpl.delUser()===========
=====UserManagerImpl.updateUser()===========
=======================================
Schema-based
式(
xml
配置)
一、類:
/**
*
定義切面
* @author dell
*
*/
public class CheckAspect {
/*
*
定義通知
advice
(
before
型)
,
標識在哪個切入點
(allSaveMethod),
織入
(
weaver
)
此方法
*/
public void checkUser(){
System.out.println("=======CheckAspect.checkUser()===========");
}
}
二、
applicationcontex.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:aop="
http://www.springframework.org/schema/aop
"
xmlns:tx="
http://www.springframework.org/schema/tx
"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
"
>
<bean id="checkAspect" class="com.CheckAspect" />
<bean id="userManager" class="com.manager.impl.UserManagerImpl" />
<aop:config>
<!--
配置切面
appect , ref
切面類
-->
<aop:aspect id="check" ref="checkAspect">
<!--
配置切入點
pointcut,
定義一個表達式
-->
<aop:pointcut
id="allSaveMethod"
expression="execution(*
com.manager.impl.UserManagerImpl.save*(..))"/>
<!--
設置
before
advice,
用
checkAspect
中的一個方法,並定位到相位的切入點
pointcut -->
<aop:before method="checkUser" pointcut-ref="allSaveMethod"/>
</aop:aspect>
</aop:config>
</beans>
三、測試用例:
public void testAspect(){
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserManager userManager = (IUserManager) factory.getBean("userManager");
userManager.saveUser("cat", "123");
userManager.delUser(1);
userManager.updateUser(1);
}
輸出結果:
=======CheckAspect.checkUser()===========
=====UserManagerImpl.saveUser()===========
=====UserManagerImpl.delUser()===========
=====UserManagerImpl.updateUser()===========
四、
Advice
中可以加入
JoinPoint
參數,內含有代理類的方法的方法
名和參數數組
import
org.aspectj.lang.JoinPoint
;
/*
*
定義通知
advice
(
before
型)
,標識在哪個切入點
(allSaveMethod),
織入(
weaver
)此方法
* JoinPoint
內含代理類的參數和方法
*/
public void checkUser(
JoinPoint joinPoint
){
Object[] args = joinPoint.getArgs();
for(int i=0; i<args.length; i++){
System.out.println("
參數
" + i + "=" + args[i]);
}
System.out.println("
代理類的方法:
" + joinPoint.getSignature().getName());
System.out.println("=======CheckAspect.checkUser()===========");
}
輸入結果:
參數
0=cat
參數
1=123
代理類的方法:
saveUser
=======CheckAspect.checkUser()===========
=====UserManagerImpl.saveUser()===========
=====UserManagerImpl.delUser()===========
=====UserManagerImpl.updateUser()===========
=======================================
注:
Aspect
默認情況下不用實現接口,但對於目標對象(
UserManagerImpl.java
)
,在默認
情況下必須實現接口;
如果沒有實現接口必須引入
CGLIB
庫
==================================
Spring AOP
用戶可能會經常使用
execution
pointcut designator
。執行表達式的格式
如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?)
除了返回類型模式
(上面代碼片斷中的
ret-type-pattern
)
,
名字模式和參數模式以外,
所有的
部分都是可選的。
返回類型模式決定了方法的返回類型必須依次匹配一個連接點。
你會使
用的最頻繁的返回類型模式是
*
,它代表了匹配任意的返回類型。
一個全稱限定的類型名
將只會匹配返回給定類型的方法。
名字模式匹配的是方法名。
你可以使用
*
通配符作爲所
有或者部分命名模式。
參數模式稍微有點複雜:
()
匹配了一個不接受任何參數的方法,
而
(..)
匹配了一個接受任意數量參數的方法
(零或者更多)
。
模式
(*)
匹配了一個接受一個
任何類型的參數的方法。
模式
(*,String)
匹配了一個接受兩個參數的方法,第一個可以
是任意類型,
第二個則必須是
String
類型。
請參見
AspectJ
編程指南的
Language Semantics
部分。
下面給出一些常見切入點表達式的例子。
任意公共方法的執行:
execution(public * *(..))
任何一個以
“set”
開始的方法的執行:
execution(* set*(..))
AccountService
接口的任意方法的執行:
execution(* com.xyz.service.AccountService.*(..))
定義在
service
包裏的任意方法的執行:
execution(* com.xyz.service.*.*(..))
定義在
service
包或者子包裏的任意方法的執行:
execution(* com.xyz.service..*.*(..))
在
service
包裏的任意連接點(在
Spring AOP
中只是方法執行)
:
within(com.xyz.service.*)
在
service
包或者子包裏的任意連接點(在
Spring AOP
中只是方法執行)
:
within(com.xyz.service..*)
實現了
AccountService
接口的代理對象的任意連接點
(在
Spring AOP
中只是方法執行)
:
this(com.xyz.service.AccountService)
注:來自百度文檔、內容僅供個人學習