目录
前言:
该文章主要使用XML的方法配置AOP
一、AOP概念
1、AOP(Aspect Oriented Programing)面向切面编程,一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构
2、AOP弥补了OOP的不足,基于OOP基础之上进行横向开发
2.1 OP规定程序开发以类为主体模型,一切围绕对象进行,完成某个任务先构建模型
2.2 AOP程序开发主要关注基于OOP开发中的共性功能,一切围绕共性功能进行,完成某个任务先构建可能遇到的所有共性功能(当所有功能都开发出来也就没有共性与非共性之分)
二、AOP的优势
-
提高代码的可重用性
-
业务代码编码更简洁
-
业务代码维护更高效
-
l业务功能扩展更便捷
三、使用步骤
1.导入依赖
<dependencies>
<!--Spring上下文核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<!--AOP的实现包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
2.创建目标接口,并创建实现类,定义目标方法(连接点)
代码如下(示例):
/**
* @Author:Yan
* @Date 2022/01/21 17:21
* @Description 目标接口
**/
public interface Target {
String method(String name);
}
/**
* @Author:Yan
* @Date 2022/01/21 17:22
* @Description 目标接口实现类
**/
public class TargetImpl implements Target {
//需要增强的目标方法
@Override
public String method(String name) {
System.out.println("TargetImpl..."+name);
return name;
}
}
3.创建通知类,定义通知方法
public class MyAdvice {
//前置通知
public void before() {
System.out.println("前置增强-->打印日志");
}
//最终通知
public void after() {
System.out.println("最终通知-->打印日志");
}
//返回后通知
public void afterRun() {
System.out.println("返回后通知-->打印日志");
}
//抛出异常后通知
public void afterThrow() {
System.out.println("抛出异常后通知-->打印日志");
}
/**
* 环绕通知 形参需要传入ProceedingJoinPoint(由Spring提供,不用自己创建)
* 必须传入ProceedingJoinPoint,否则跟前置通知没有区别
* ProceedingJoinPoint的方法
* 1、public Object proceed(Object[] args) throws Throwable 用于调用目标方法
* 2、Object[] getArgs(); 用于获取目标方法的参数,可用于修改目标方法的参数
* @param pjp
* @return
* @throws Throwable
*/
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object proceed = null;
//前置通知
before();
try {
//获取参数
pjp.getArgs()[0] = "李四";
System.out.println("环绕通知-->打印日志");
//调用proceed()方法 这里就会去调用目标方法
// pjp.proceed();
//调用proceed()方法 并将设置好的值传递回去 这样子就可以修改目标方法的参数值
proceed = pjp.proceed(pjp.getArgs());
//返回后通知
afterRun();
} catch (Throwable throwable) {
//抛异常时通知
afterThrow();
throwable.printStackTrace();
} finally {
//最终通知
after();
}
return proceed;
}
}
4.创建Spring核心配置文件(基于xml配置方法)
<!--
步骤:
1、使用bean标签创建目标实现类对象,并交给Spring的IOC容器管理
2、使用bean标签创建通知类对象,并交给Spring的IOC容器管理
3、使用<aop:config>定义aop的配置
3.1 在<aop:config>里面使用<aop:aspect ref="通知类的唯一标识">配置切面,使用ref属性,获取IOC容器中已经创建好的通知类
3.2 在<aop:aspect>里面使用<aop:pointcut>设置切入点
3.3 配置切入点的标签<aop:通知类型 method="通知类中的方法" pointcut="切入点表达式">可以定义多个切入点
-->
<!-- 1、使用bean标签创建MyAdvice通知类,交给Spring管理 -->
<bean id="myAdvice" class="com.itheima.Advice.MyAdvice"/>
<!-- 2、使用bean标签创建TargetImpl的对象的,交给Spring管理 -->
<bean id="target" class="com.itheima.service.impl.TargetImpl"/>
<!--
3、使用<aop:com.itheima.config>标签设置AOP
<aop:aspect> 设置通知对应的和切入点
-->
<aop:config>
<!-- 配置切入点表达式 这里直接指定目标方法名(method)-->
<aop:pointcut id="po" expression="execution(* com.itheima..*.method(..))"/>
<aop:aspect ref="myAdvice">
<!-- <aop:before method="before" pointcut="execution(* com.itheima..*.method(..))"/>
<aop:after method="after" pointcut="execution(* com.itheima..*.method(..))"/>
<aop:after-returning method="afterRun" pointcut="execution(* com.itheima..*.method(..))"/>
<aop:after-throwing method="afterThrow" pointcut="execution(* com.itheima..*.method(..))"/>-->
<!-- 指定了通知类的方法 -->
<aop:around method="around" pointcut-ref="po"/>
</aop:aspect>
</aop:config>
5.测试
/**
* ClassPathXmlApplicationContext对象是用于读取xml格式的配置文件,需要传入xml格式的Spring文件
* <T> T getBean(Class<T> requiredType) 方法,需要传入由IOC容器管理的目标对象
*/
@Test
public void method() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Target target = context.getBean(Target.class);
String s = target.method("哈哈");
System.out.println(s);
}
6.测试结果
前置增强-->打印日志
环绕通知-->打印日志
TargetImpl...李四
返回后通知-->打印日志
最终通知-->打印日志
李四
注意事项:
- 环绕通知方法必须传入ProceedingJoinPoint对象的形参,并且需要调用目标方法,否则目标方法不会执行
- Application.xml文件中
ref=通知类的唯一标识(必须已经由IOC容器管理的通知类)<aop:aspect ref="myAdvice"> 其中<aop:通知类型 method=通知方法 pointcut-ref=切入点表达式(用于匹配目标方法的)> <aop:around method="around" pointcut-ref="po"/> </aop:aspect> 当修改了通知方法时,记得要修改通知类型,否则可能达不到想要的效果