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/aspectj/*.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()===========");
}
}
测试服务类:
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/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"
>
<!-- 启用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库