导入依赖
<!-- AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.20</version>
</dependency>
spring.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation=" http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 自动扫包-->
<context:component-scan base-package="com.lmh.AOP"></context:component-scan>
<!-- 为委托对象自动生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
● aop:aspectj-autoproxy, Spring loC容器会结合切面对象和委托对象自动生成动态代理对象,AOP底层就是通过动态代理机制来实现的。
● @Component,将切面类加载到loC容器中。
● @Aspect, 表示该类是一个切面类。
● @Before, 表示方法的执行时机是在业务方法之前
● @After, 表示方法的执行时机是在业务方法之后
● execution表达式表示切入点是Calimpl类中的add方法。
● @AfterReturning,表示方法的执行时机是在业务方法返回结果之后,returning 是将业务方法的返回值与切面类方法的形参进行绑定。
● @AfterThrowing,表示方法的执行时机是在业务方法抛出异常之后,throwing 是将业务方法的异常与切面类方法的形参进行绑定。
创建切面类
/**
* author: lmh
* date:2022/6/17
*/
@Component
@Aspect
public class LoggerAspect {
//方法名 ..是参数占位符 *是适配所有方法
@Before("execution(public int com.lmh.AOP.impl.Calimpl.*(..))")
public void before(JoinPoint joinPoint) {
//得到方法名
String name = joinPoint.getSignature().getName();
//得到参数
String args = Arrays.toString(joinPoint.getArgs());
System.out.println(name + "方法的参数是:" + args);
}
@After("execution(public int com.lmh.AOP.impl.Calimpl.*(..))")
public void after(JoinPoint joinPoint) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法执行完毕");
}
//返回值信息
@AfterReturning(value = "execution(public int com.lmh.AOP.impl.Calimpl.*(..))", returning = "result")
public void afterReturn(JoinPoint joinPoint, Object result) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法的结果是:" + result);
}
//抛出异常时 打印的信息
@AfterThrowing(value = "execution(public int com.lmh.AOP.impl.Calimpl.*(..))", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Exception ex) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法抛出异常" + ex);
}
}
委托类也需要添加@Component注解
/**
* author: lmh
* date:2022/6/17
*/
@Component
public class Calimpl implements Cal {
int result;
@Override
public int add(int num1, int num2) {
result = num1 + num2;
return result;
}
@Override
public int sub(int num1, int num2) {
result = num1 - num2;
return result;
}
@Override
public int mul(int num1, int num2) {
result = num1 * num2;
return result;
}
@Override
public int div(int num1, int num2) {
result = num1 / num2;
return result;
}
main
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_aop.xml");
Cal cal =(Cal) applicationContext.getBean("calimpl");
cal.add(10, 3);
cal.sub(9, 5);
cal.mul(5, 3);
cal.div(5, 0);
AOP的概念:
- 切面对象:根据切面抽象出来的对象,Calimpl 所有方法中需要加入日志的部分,抽象成一个切面类 LoggerAspect。
- 通知:切面对象具体执行的代码,即非业务代码,LoggerAspect 对象打印日志的代码。
- 目标:被横切的对象,即Calimpl, 将通知加入其中。
- 代理:切面对象、通知、目标混合之后的结果,即我们使用JDK动态代理机制创建的对象。
- 连接点:需要被横切的位置,即通知要插入业务代码的具体位置。