目录
AoP基本实现
AoP 配置标签结构
<aop:config>
<!-- 定义切点的位置 -->
<aop:pointcut />
<!-- 设置切面 -->
<aop:aspect >
<!-- 设置切点 -->
<aop:Before></aop:Before>
</aop:aspect>
</aop:config>
aop:aspect 子标签
Pointcut
标签 可以设置多个,但必须在aspect
标签之前
Before ..
标签必须指定pointcut-ref
属性
Before
Before 将方法执行之前作为切入点
After
After 将方法结尾作为切入点
After-throwing
After-throwing 将方法中出现异常之后作为切入点
throwing 属性,设置抛出的异常信息参数(Exception 类型)
,在切入的方法中必须设置相应的参数(如果含有JoinPoint参数,必须在此之后
)
After-returning
After-returning 将方法的返回值之后作为切入点
returning 属性,传递返回值内容(Object 类型
),切入的方法需要有相应的参数(如果含有JoinPoint参数,必须在此之后
)
Around
实例
AoP配置
<aop:config>
<!-- 设置多个切点 -->
<aop:pointcut id="point" expression="execution(* com.yang..*.*(..))"/>
<aop:pointcut id="point1" expression="execution(* com.yang.test.*.*(..))"/>
<aop:aspect ref="myLogger">
<aop:before method="BeforeMethod" pointcut-ref="point" />
<aop:after method="AfterMethod" pointcut-ref="point" />
<aop:after-throwing method="AfterThrowing" pointcut-ref="point" throwing="e"/>
<aop:after-returning method="AfterReturning" pointcut-ref="point" returning="value_return" />
<aop:after method="AfterMethod" pointcut-ref="point2" />
</aop:aspect>
<!-- 位置错误 -->
<!--<aop:pointcut id="point1" expression="execution(* com.yang.test.*(..))"/> -->
<aop:aspect ref="myLogger">
<aop:before method="BeforeMethod" pointcut-ref="point1" />
<aop:after method="AfterMethod" pointcut-ref="point1" />
<aop:after-throwing method="AfterThrowing" pointcut-ref="point1" throwing="e"/>
<aop:after-returning method="AfterReturning" pointcut-ref="point1" returning="value_return" />
<aop:after method="AfterMethod" pointcut-ref="point1" />
</aop:aspect>
</aop:config>
Logger类
package com.yang.logger;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @author LiYang
* @Project Name: Spring-AoP-Demo
* @Package Name: com.yang.aop
* Created by MacBook Air on 2020/09/01.
* Copyright © 2020 LiYang. All rights reserved.
*/
@Component("myLogger")
public class MyLogger {
private Logger logger = Logger.getLogger(MyLogger.class);
public void BeforeMethod(JoinPoint joinPoint){
//
String name = joinPoint.getSignature().getName();
Object target = joinPoint.getTarget();
Object[] args = joinPoint.getArgs();
logger.info(">> BeforeMethod >>>" + name + ":" + target + ":" + Arrays.toString(args));
}
public void AfterMethod(JoinPoint joinPoint){
logger.info(">> AfterMethod >>>" + joinPoint.getSignature().getName() );
}
public void AfterThrowing(JoinPoint joinPoint, Exception e){
logger.info(">> AfterThrowing >>>" + joinPoint.getSignature().getName() + ":Error Message:" + e.getMessage()) ;
}
public void AfterReturning(JoinPoint joinPoint, Object value_return){
logger.info(">> afterReturning >>>" + joinPoint.getSignature().getName() + ":Return Value:" + value_return.toString() );
}
}
被切入类
package com.yang.test;
import org.springframework.stereotype.Component;
/**
* @author LiYang
* @Project Name: Spring-AoP-Demo
* @Package Name: com.yang.test
* Created by MacBook Air on 2020/09/01.
* Copyright © 2020 LiYang. All rights reserved.
*/
@Component("demo")
public class Demo {
public String method1(String arg1, int id){
try {
System.out.println("——————— Start method ———————");
int x = 1 / 0;
System.out.println(x);
return "Finish";
}catch (Exception e){
return "Error";
}
finally {
System.out.println("——————— End method ———————");
}
}
}
测试
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Demo demo = ((Demo) applicationContext.getBean("demo"));
demo.method1("参数1",2);
}
}
运行结果
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> BeforeMethod >>>method1:com.yang.test.Demo@12359a82:[参数1, 2]
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> BeforeMethod >>>method1:com.yang.test.Demo@12359a82:[参数1, 2]
——————— Start method ———————
——————— End method ———————
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> AfterMethod >>>method1
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> AfterMethod >>>method1
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> AfterReturning >>>method1:Return Value:Error
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> AfterReturning >>>method1:Return Value:Error
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> AfterMethod >>>method1
09-03 14:52:45[INFO]com.yang.logger.MyLogger >> AfterMethod >>>method1
环绕增强
环绕增强可以完成以上所有的增强方法
基本实现
<!-- 配置环绕增强 -->
<aop:config>
<aop:pointcut id="point_around" expression="execution(* com.yang.test.Demo2.*(..))"/>
<aop:aspect ref="myLogger">
<aop:around method="aroundMethod" pointcut-ref="point_around" />
</aop:aspect>
</aop:config>
/**
* ProceedingJoinPoint extends JoinPoint
* @param joinPoint
*/
public void aroundMethod(ProceedingJoinPoint joinPoint){
// 前置增强方法
Object object = null;
logger.info("增强前");
try {
// 类似拦截器 放行后执行方法, 并将方法的返回值作为 proceed 方法的返回值(后置增强)
object = joinPoint.proceed();
} catch (Throwable e) {
// 抛出的异常作为 切入方法所抛出的异常(异常抛出增强)
logger.info("Error:"+ e.getMessage());
}
// 最终增强
logger.info("增强后:" + object);
}
@Component("demo")
public class Demo {
public String method1(String arg1, int id){
try {
System.out.println("——————— Start method ———————");
int x = 1 / 0;
System.out.println(x);
return "Finish";
}catch (Exception e){
return "返回值:Error";
}
finally {
System.out.println("——————— End method ———————");
}
}
}
运行过程如图所示
将
Demo
作为被切入对象
总结
增强处理类型 | 特点 |
---|---|
Before | 前置增强处理,在目标方法前织入增强处理 |
AfterReturning | 后置增强处理,在目标方法正常执行(不出现异常)后织入增强处理 |
AfterThrowing | 异常增强处理,在目标方法抛出异常后织入增强处理 |
After | 最终增强处理,不论方法是否抛出异常,都会在目标方法最后织入增强处理 |
Around | 环绕增强处理,在目标方法的前后都可以织入增强处理 |