注:与前面的笔记有一点地方不一样,无伤大雅,笔记要点在代码中
AOP的一丁点基础:学习笔记(05):轻松搞定Spring全家桶(初识篇)-面向切片编程AOP
使用AspectJ基于XML开发AOP:
一、创建项目,导入相关jar包:(点击下载)
二、创建一个接口:/AOPProjectByAspectJXml/src/com/aop/UserDao.java
package com.aop;
public interface UserDao {
public void addUser(String id,String name);
}
三、创建接口实现类:/AOPProjectByAspectJXml/src/com/aop/UserDaoImpl.java
package com.aop;
public class UserDaoImpl implements UserDao {
@Override
public void addUser(String id, String name) {
// TODO Auto-generated method stub
//制造一个异常用于测试
//String a = null;a.length();
System.out.println(name+"的id是:"+id);
}
}
四、创建切面类:/AOPProjectByAspectJXml/src/com/aop/LogAspect.java
注:一部分笔记在这个类的注释中
package com.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class LogAspect {
//配置为前置通知
public void myBefore(JoinPoint joinpoint) {
//通过joinpoint获取目标对象的一些信息
System.out.println("===前置通知-目标对象:"+joinpoint.getTarget());
System.out.println("===前置通知-方法名称:"+joinpoint.getSignature().getName());
System.out.println("-------------------------------");
}
/**
* 配置为返回(最终)通知:
* 目标方法正常结束后执行的代码,如果目标方法出现异常则不执行
* 在目标方法返回结果之后执行的通知,
* 返回通知是可以访问到方法的返回值的
*/
public void myAfterReturning(JoinPoint joinpoint) {
System.out.println("===AfterReturning返回(最终)通知-目标对象:"+joinpoint.getTarget());
System.out.println("===返回(最终)通知-方法名称:"+joinpoint.getSignature().getName());
}
/**
* 配置为后置通知:
* 就算目标方法抛出异常,通知也会执行
* 但是无法访问目标方法的返回值,因为此时还没有返回
*/
public void myAfter(JoinPoint joinpoint) {
System.out.println("===后置通知-目标对象:"+joinpoint.getTarget());
System.out.println("===后置通知-方法名称:"+joinpoint.getSignature().getName());
System.out.println("--------目标异常也会执行---------------");
}
/**
* 配置为环绕通知:
* 需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数决定是否执行目标方法。
* 而且环绕通知必须有返回值,返回值即为目标方法的返回值
*/
public Object myAround(ProceedingJoinPoint procee) throws Throwable {
System.out.println("===环绕通知开始-目标对象:"+procee.getTarget());
System.out.println("-------------------------------");
Object object = procee.proceed();//调用目标对象方法
System.out.println("-------------------------------");
System.out.println("===环绕通知结束-目标对象:"+procee.getTarget());
System.out.println("-------------------------------");
return object;
}
//异常通知:e用来获取异常的有关信息
public void myAfterThrowing(JoinPoint joinpoint, Throwable e) {
System.out.println("===异常通知"+e.getMessage());
System.out.println("-------------------------------");
}
}
五、配置文件:/AOPProjectByAspectJXml/resource/applicationContext.xml
注:另一部分笔记在这个配置文件中,另外 execution表达式的详细结束在另外的博文笔记中
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd ">
<!-- 定义目标对象 -->
<bean id="userDao" class="com.aop.UserDaoImpl"></bean>
<!-- 定义切面 -->
<bean id="logAspect" class="com.aop.LogAspect"></bean>
<!-- AOP配置关系 -->
<aop:config>
<aop:aspect ref="logAspect">
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.aop.UserDao.addUser(..))" id="myPointcut"/>
<!-- execution表达式详解看其他笔记,这里写不开-->
<!-- 前置通知 -->
<aop:before method="myBefore" pointcut-ref="myPointcut"/>
<!-- 返回(最终)通知 -->
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut"/>
<!-- 后置通知 -->
<aop:after method="myAfter" pointcut-ref="myPointcut"/>
<!-- 环绕通知 -->
<aop:around method="myAround" pointcut-ref="myPointcut"/>
<!-- 异常通知 相比其他额外需要配置接收异常信息的参数 -->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointcut" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
六、测试类:/AOPProjectByAspectJXml/src/com/aop/TestUserDao.java
package com.aop;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
class TestUserDao {
@Test
void testAddUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = context.getBean("userDao", UserDao.class);
userDao.addUser("T11", "Tom");
}
}
七、测试结果:
- 目标方法有异常时:
- 目标方法没有异常时:
八、补充笔记:execution函数的相关用法