1. AOP概念
AOP(Aspect-Oriented Programming,面向切面编程),简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或业务封装起来,再把封装功能整合到业务中。好处:便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
AOP的核心思想就是“将应用程序中的业务逻辑同对其提供支持的通用服务进行分离"
例如:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
2.AOP实现准备
(1),首先在IOC的基础上添加依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.3.12</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
(2),编写服务接口和服务类
服务接口:
public interface UserService {
/**
* 模拟添加
*/
void add();
/**
* 模拟删除
*/
void delete();
/**
* 模拟更新
*/
void update();
/**
* 模拟查询
*/
void query();
}
服务类:
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("模拟添加");
}
@Override
public void delete() {
System.out.println("模拟删除");
}
@Override
public void update() {
System.out.println("模拟更新");
}
@Override
public void query() {
System.out.println("模拟查询");
}
}
3.AOP的实现
(1),方式一:使用原生spring API接口
编写增强类
public class MethodLog implements MethodBeforeAdvice {
//method:要执行目标对象方法
//objects:参数
//o:目标对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
在配置文件spring-aop.xml中配置:
<!--注册bean-->
<bean id="userService" class="com.li.service.impl.UserServiceImpl"/>
<bean id="methodLog" class="com.li.log.MethodLog"/>
<!--方式一:使用原生spring API接口-->
<!--配置aop:需要导入aop的约束-->
<aop:config>
<!--切入点:expression:表达式,expression(要执行的位置)-->
<aop:pointcut id="pointcut" expression="execution(* com.li.service.impl.UserServiceImpl.add*(..))"/>
<!--执行环绕-->
<aop:advisor advice-ref="methodLog" pointcut-ref="pointcut"/>
</aop:config>
编写测试类:
public class AOPTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
//动态代理代理的是接口
UserService userService = (UserService) context.getBean("userService");
userService.delete();
userService.update();
userService.add();
userService.query();
}
}
测试结果:
(2),方式二:自定义类
编写增强类:
public class DivPointCut {
public void befor(){
System.out.println("============方法执行前============");
}
public void after(){
System.out.println("============方法执行后============");
}
}
在配置文件spring-aop.xml中配置:
<!--注册bean-->
<bean id="userService" class="com.li.service.impl.UserServiceImpl"/>
<!--方式二:自定义-->
<bean id="div" class="com.li.div.DivPointCut"/>
<aop:config>
<aop:aspect ref="div">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.li.service.impl.UserServiceImpl.add*(..))"/>
<!--通知-->
<aop:before method="befor" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
编写测试类:(测试类不变)
public class AOPTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
//动态代理代理的是接口
UserService userService = (UserService) context.getBean("userService");
userService.delete();
userService.update();
userService.add();
userService.query();
}
}
测试结果:
(3),方式三:采用注解
编写增强类:
@Aspect //生成代理对象
@Component
public class Log {
//后置通知
@AfterReturning(pointcut = "execution(* com.li.service.impl.UserServiceImpl.add(..))")
public void add(){
System.out.println("==========模拟日志添加==========");
}
//前置通知
@Before("execution(* com.li.service.impl.UserServiceImpl.delete(..))")
public void before(){
System.out.println("==========模拟日志删除==========");
}
}
在配置文件spring-aop.xml中配置:
<!--开启注解扫描-->
<context:component-scan base-package="com.li"/>
<!--开启Aspect生成代理对象-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
注意:要在业务类上加上一个@Component注解,否则会有可能扫描不到
编写测试类:
public class AOPTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
//动态代理代理的是接口扫描userServiceImpl
UserService userService = (UserService) context.getBean("userServiceImpl");
userService.delete();
userService.update();
userService.add();
userService.query();
}
}
测试结果: