好奇宝宝就要问了:什么是AOP?
Spring AOP(Aspect-Oriented Programming,面向切面编程)是一种编程思想,它允许我们在不修改业务逻辑代码的情况下,对程序的特定部分进行横切关注点的处理。简单来说,它就像是程序中的“补丁”,可以让我们把一些通用的功能(比如日志记录、权限检查等)应用到程序的多个地方,而不需要在每个地方都重复编写这些代码。
想象一下,你有一个登录功能,你想在登录前将用户操作日志存储在数据库,在用户操作后也将日志存储在数据库,类似于叠汉堡(增强),不修改登录功能源代码的情况下,把日志操作增强到登录功能中。
一、了解AOP有哪些专业术语
1. 切面(Aspect):切面是面向切面编程中的一个核心概念,它定义了一组横切关注点的模块化,比如日志记录、事务管理等。切面由切点和通知组成。
2. 连接点(Join Point):连接点指的是程序执行过程中的一个点,在这个点上可以插入切面,比如方法的调用、异常的抛出等。在Spring AOP中,连接点总是方法的执行。
3. 切入点(Pointcut):切入点是一组匹配连接点的规则,用于确定哪些连接点会被切面所影响。通过切入点表达式,你可以指定哪些方法的执行需要被切面处理。
4. 通知(Advice)或增强(Advice):通知是切面的一部分,它定义了在连接点上执行的具体行为。通知可以有不同的类型,比如在方法执行之前、之后、抛出异常时等。
5. 目标对象(Target Object):目标对象是被一个或多个切面所通知的对象。它是业务逻辑的载体,也就是我们通常所说的“业务对象”。
6. 织入(Weaving):织入是将切面应用到目标对象来创建一个被通知的对象的过程。这可以在编译时、类加载时或运行时完成。
7. 代理(Proxy):代理是AOP框架创建的一个对象,它包含了目标对象的所有方法。当代理对象的方法被调用时,AOP框架会根据定义的切面来决定是否执行通知。在Spring AOP中,有两种代理类型:JDK动态代理和CGLIB代理。
8. 织入器(Weaver):织入器是负责将切面应用到目标对象的组件。它负责在运行时将切面和目标对象结合起来。
9. 引入(Introduction):引入是一种特殊的切面,它允许我们向目标对象添加新的方法或属性,而不需要修改目标对象的代码。
二、看不懂没关系,直接上代码演示1(基于JDK动态代理的AOP实现)一共7个步骤
1.创建项目:详细教程看(0基础保姆教程)-JavaEE开课啦!--01课程(创建Spring项目)-优快云博客
2.基于JDK动态代理的AOP实现不需要引入依赖,本实现仅通过java.lang.reflect.Proxy类实现的
3.创建用户操作的实现接口(UserDao)
在目录中创建Dao软件包,用于存放逻辑程序
在软件包中创建java类,选择接口类型
在接口中编写登录功能的接口(本次教程仅演示逻辑,不实现真实登录操作)
package com.ljl.Dao;
public interface UserDao {
//登录功能接口
public void login();
}
4.创建用户操作的具体实现类,继承于实现接口(UserDaoImpl.java)
创建Impl软件包,创建用户登录功能实现类,继承于接口
鼠标定位到报错位置,按下键盘alt + Enter键,选择实现方法-点击确定
模拟输出“登陆成功”在控制台
5.创建切面类方法,存放需要切入的方法:登录前日志存储、登录后日志存储(MyAspect.java)
创建MyAspect切面类,存放需要织入的功能
package com.ljl;
public class MyAspect {
//模拟登录前的日志记录
public void before() {
System.out.println("登录前日志记录");
}
//模拟登录后的日志记录
public void after() {
System.out.println("登录后日志记录");
}
}
6.创建代理类,生成代理方法(MyProxy.java)
创建MyProxy代理类,继承于InvocationHandler
7.创建测试类,编写测试代码(Test.java)
在Main.java文件中,编写测试代码,主要为创建代理对象和目标对象,获取增强后的对象,使用方法
成功织入方法
三、看不懂没关系,直接上代码演示2(基于注解的AOP实现)
1.@Aspect:配置切面
2.@Pointcut:配置切入点
3.@Before:配置前置通知
4.@After:配置后置通知
5.@Around:配置环绕通知
============================Begin===============================
1.创建Spring项目,在pom文件中引入Spring-context Spring-aop aspectjweaver依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ljl</groupId>
<artifactId>teach_Spring_JDK_AOP</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.1.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
</project>
2.创建applicationContext.xml配置文件,声明context和aop
<?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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 注册Bean,声明com.ljl.dao下的所有使用了注解的类都注册Bean-->
<context:component-scan base-package="com.ljl"/>
<!-- 开启aspectj自动代理-->
<aop:aspectj-autoproxy/>
</beans>
3.创建用户登录接口
package com.ljl.Dao;
public interface UserDao {
//登录功能接口
public void login();
}
4.创建用户登录实现类
package com.ljl.Dao.Impl;
import com.ljl.Dao.UserDao;
import org.springframework.stereotype.Component;
//声明Bean
@Component
public class UserDaoImpl implements UserDao {
@Override
public void login() {
System.out.println("登录成功!");
}
}
5.创建切面类
package com.ljl;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//注册Bean
@Component
//配置切面
@Aspect
public class MyAspect {
//定义切点
@Pointcut("execution( * com.ljl.Dao.Impl.UserDaoImpl.*(..))")
public void myPointcut() {
}
//模拟登录前的日志记录
@Before("myPointcut()")
public void before(JoinPoint joinPoint) {
System.out.println("登录前日志记录");
}
//模拟登录后的日志记录
@After("myPointcut()")
public void after(JoinPoint joinPoint) {
System.out.println("登录后日志记录");
}
}
6.创建测试程序
package com.ljl;
import com.ljl.Dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//引入配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取到配置文件中已经声明的Bean
UserDao userDaoImpl = (UserDao) context.getBean("userDaoImpl");
//调用增强后的方法
userDaoImpl.login();
}
}
7.运行程序