SpringAOP是什么?为什么要有SpringAOP?
原文:SpringAOP是什么?为什么要有SpringAOP?
一、有SpringAOP之前
简单的开发场景,只需要写简单的业务逻辑,比如CRUD
但是在执行具体的逻辑之前,需要进行权限校验,或者在具体的逻辑之后,需要日志记录呢?
这样就增加了很多代码,而且增加的这些代码都是差不多的
既然如此,那我们抽出来吧!在这个类里面写一个私有的方法。
代码少了很多,但是如果其他的类也需要用到权限校验和日志记录呢?
难道也要在其他类里面写私有方法吗?这也太麻烦了。
为了解决这个问题,有两种方法。
第一种:将这个私有方法抽出来不就好了,我直接写两个工具类,一个是权限校验,一个是日志记录,谁用谁调用。
第二种:我直接搞一个父类,谁用我就让它继承这个父类,这样就能直接调用父类的方法。
但是不论是第一种还是第二种其实都会侵入业务类的方法逻辑,那么有没有一种方法,能在没有对业务核心代码侵入性的前提下,给业务核心代码添加额外的功能呢?
这时候AOP就出来了,也就是所谓的面向切面编程。
首先来看一下AOP的概念:
切入点:
想额外添加功能的方法
切面:
权限检查、日志记录等这些增强逻辑的方法在的类
通知:
在目标方法运行的什么时机来执行某个增强逻辑
目标方法前还是目标方法后
切入点表达式:
规定增强逻辑需要去增强什么方法
二、有SpringAOP之后
使用方法:
maven依赖
<dependencies>
<!--导入Spring Context核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<!--Spring AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.1</version>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<!--Junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
切入点
package com.moon.aop.bean;
/**
* @Author moon
* @Date 2023/10/15 15:55
* @Description 切入点
*/
public class UserService {
public void addUser() {
System.out.println("添加用户...");
}
public void queryUser() {
System.out.println("查询用户...");
}
public void editUser() {
System.out.println("编辑用户...");
}
public void deleteUser() {
System.out.println("删除用户...");
}
}
切面
package com.moon.aop.bean;
/*
* 底层依赖Aspect的注解【但是原理不同】
* */
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* @Author moon
* @Date 2023/10/15 15:58
* @Description 切面,里面放的增强逻辑
*/
@Aspect
public class UserAspect {
/*
* 这就是传说中上文所谓的切入点表达式
* */
@Pointcut(value = "execution(* com.moon.aop.bean.UserService.*(..))")
public void point() {
}
/*
* 这就是增强逻辑
* @Before、@After就是所谓的通知
* */
@Before(value = "point()")
public void beforeRun() {
System.out.println("在目标方法执行前开始执行");
}
@After(value = "point()")
public void afterRun() {
System.out.println("在目标方法执行后开始执行");
}
}
配置类:用来初始化和加载Spring的IOC容器
package com.moon.aop.bean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @Author moon
* @Date 2023/10/15 16:07
* @Description 用该类来初始化和加载IOC容器
*/
@Configuration
public class SpringConfig {
@Bean
public UserAspect userAspect() {
return new UserAspect();
}
@Bean
public UserService userService() {
return new UserService();
}
}
Junit单元测试
import com.moon.aop.bean.SpringConfig;
import com.moon.aop.bean.UserService;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author moon
* @Date 2023/10/15 16:32
* @Description
*/
public class AOPTest {
@Test
public void test01() {
/*
* 通过配置类初始化IOC容器
* */
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
/*
* 获取目标对象,Bean
* */
UserService userService = context.getBean(UserService.class);
userService.addUser();
}
}
AOP并没有生效
此时userService.getClass().getName()的值为
那是因为Spring并没有开启AOP,需要我们手动开启
package com.moon.aop.bean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @Author moon
* @Date 2023/10/15 16:07
* @Description 用该类来初始化和加载IOC容器
*/
@Configuration
/*
* 手动开启AOP功能
* */
@EnableAspectJAutoProxy
public class SpringConfig {
@Bean
public UserAspect userAspect() {
return new UserAspect();
}
@Bean
public UserService userService() {
return new UserService();
}
}
成功!
此时userService.getClass().getName()的值为