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)
注:来自百度文档、内容仅供个人学习