Spring AOP
面向切面编程,是一个抽象化的面向对象编程,是对面向对象的一种补充。底层采用动态代理的机制。常用来
- 打印日志
- 事务
- 权限处理
以打印日志为例
现有一个计算机Cal
接口,需要在实现类CalImpl
中打印日志,打印方法的参数已经方法的结果信息。
Cal
public interface Cal {
// 加
int add(int num1,int num2);
// 减
int sub(int num1,int num2);
// 乘
int mul(int num1,int num2);
// 除
int div(int num1,int num2);
}
CalImpl
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
System.out.println("add的方法参数为:" + num1 + "," + num2);
int result = num1 + num2;
System.out.println("add方法的结果为:" + result);
return result;
}
@Override
public int sub(int num1, int num2) {
System.out.println("sub的方法参数为:" + num1 + "," + num2);
int result = num1 - num2;
System.out.println("sub方法的结果为:" + result);
return result;
}
@Override
public int mul(int num1, int num2) {
System.out.println("mul的方法参数为:" + num1 + "," + num2);
int result = num1 * num2;
System.out.println("mul方法的结果为:" + result);
return result;
}
@Override
public int div(int num1, int num2) {
System.out.println("div的方法参数为:" + num1 + "," + num2);
int result = num1 / num2;
System.out.println("div方法的结果为:" + result);
return result;
}
}
在此方法中,日志和业务混合在一起,AOP
要做的就是将日志代码全部抽象出去进行处理,计算器方法中只保留核心的业务代码。做到核心业务代码和非业务代码的解耦合。
使用AOP实现
在方法执行前切打一个切面,在方法的结束前打一个切面,用来打印日志信息
具体实现
1、导包
<!--aspect-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
2、创建切面类(Aspect)
@Component
@Aspect // 表示是一个切面类
public class CalAspect {
/**
* 方法结束之前执行
* @param joinPoint 连接点,获取连接的方法的参数等信息
*/
@Before(value = "execution(public int com.demo.aop.CalImpl.*(..))")
public void before(JoinPoint joinPoint) {
// 获取方法名字
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法的参数是:"+ Arrays.toString(joinPoint.getArgs()));
}
/**
* 方法return之后执行
* @param joinPoint 连接点,获取连接的方法的参数等信息
* @param result 方法的返回值
*/
@AfterReturning(value = "execution(public int com.demo.aop.CalImpl.*(..))",returning = "result")
public void afterReturning(JoinPoint joinPoint,Object result){
// 获取方法名字
String name = joinPoint.getSignature().getName();
System.out.println(name+"返回的结果为:"+result);
}
}
3、实现类添加@Component注解
4、配置自动扫包,开启自动生成动态代理
bean.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启自动扫描包-->
<context:component-scan base-package="com.demo.aop"></context:component-scan>
<!--自动生成代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
5、测试
当日志信息需要改变时,我们只需要改变切面类中的打印信息即可,实现了核心代码和非业务代码的解耦合。
AOP的执行原理
容器中的计算器类通过切面对象自动生成代理对象,对代理对象进行操作。
一个代理对象只能对应一个目标类