写在前面:kissing_heart:
大一电子信息工程新生,请多多关照,希望能在 InfoQ 社区 记录 自己的学习历程!
【Spring 学习笔记】系列教程基于 Spring 5.2.10.RELEASE 讲解。
一、AOP 简介
前面说过, Spring 的核心思想就是 IoC 和 AOP ,有关 IoC 的内容已经介绍过一部分了,接下来就来讲下 Spring 另一大重点: AOP 。
1、什么是 AOP
AOP ,“ Aspect Oriented Programming ”,译为“ 面向切面编程 ”,和 OOP(面向对象编程)类似, 它也是一种编程思想 。
2、AOP 的作用(特点)
代理模式
Spring AOP 的实现原理是 代理模式 ,AOP 的作用是 通过代理类为原始类增加一些额外功能 :如日志管理、权限管理、事务管理、异常管理等一些 非业务性功能 。
无入侵式
与传统的公共方法不同,Spring AOP 并不是直接调用的,AOP 是通过 横向的抽取机制 实现的。它将一些 非业务的通用功能 抽取出来单独维护,并 通过配置文件或注解的形式定义这些功能 要以哪种方式作用在哪个模块中,可以在无须修改任何业务代码的基础上完成对这些通用功能的调用和修改,即 无入侵式 的。
解耦合
事务与非事务功能分离,Spring AOP 还减少代码的重复,让我们更专注于专注业务逻辑代码。
3、AOP 相关的专业术语
4、AOP 框架
目前最流行的 AOP 实现(框架)主要有两个,分别为 Spring AOP 和 AspectJ 。
- 注:一般这两个框架一起整合使用。
二、AOP 入门案例
SpringAOP 的开发有两种方式,XML 和 注解, 本篇文章及之后的教程都 使用注解开发 演示.
1、添加 AOP 依赖
在 pom.xml 文件里添加 Spring AOP 和 AspectJ 的 jar 包依赖
- Spring AOP使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。
- AspectJ是一个基于 Java 语言的 AOP 框架。从 Spring2.0 开始,Spring AOP 引入对 Aspect 的支持,AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的织入。
<dependencies>
<!--包含Spring AOP:有基本的AOP功能-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--AspectJ框架有更强大的AOP功能-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
</dependencies>
复制代码
可以看到 spring-context 中已经导入了 spring-aop ,所以不需要再单独导入 spring-aop

2、创建目标接口和实现类
目标接口和实现类就是所谓的 Target(目标),即要被代理的对象。
/*UserDao接口*/
public interface UserDao {
public void add();
public void delete();
public void update();
public void select();
}
/*UserDaoImpl实现类*/
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("正在执行 UserDao 的 add 方法");
}
@Override
public void delete() {
System.out.println("正在执行 UserDao 的 delete 方法");
}
@Override
public void update() {
System.out.println("正在执行 UserDao 的 update 方法");
}
@Override
public void select() {
System.out.println("正在执行 UserDao 的 select 方法");
}
}
复制代码
3、创建切面类(通知类)
3.1 定义切面 @Aspect
通过 @Aspect 注解将一个 Bean 定义为切面。
@Component//将这个类定义成 Bean
@Aspect//将这个Bean定义为切面
public class MyAdvice {
}
复制代码
3.2 定义切点 @Pointcut
在 AspectJ 中,我们可以使用 @Pointcut 注解用来定义一个切点。
//切点方法必须是private,无返回值,无参数
@Pointcut(value ="execution(* com.bighorn.*.*Dao.*(..))")
private void pointCut() {
}
复制代码
注意:
- 定义为切点的方法是一个无意义的 private 方法 ,即无参数、无返回值(void)、无方法体
- @Pointcut 注解中有一个 value 属性,这个属性的值就是 切入点表达式 (插个眼在这,下篇文章详细嗦嗦)
3.3 定义通知
**通知(Advice)**就是将共性功能抽取出来后形成的方法,即对切入点增强的内容
通知有很多类型:前置通知、后置通知、环绕通知、异常通知、返回通知。(插个眼在这,下篇文章详细嗦嗦)
通知注解中有一个 value 属性,value 属性的取值就是这些 通知(Advice) 所要 织入(Weaving) 的 切点(PointCut) ,它既可以是切入点表达式,也可以是切入点引用(切入点对应的方法名称)
//使用切入点引用
@Before("MyAdvice.pointCut()")
public void beforeAdvice() {
System.out.println("这是前置通知……");
}
//使用切入点表达式
@After(value ="execution(* com.bighorn.*.*Dao.*(..))")
public void afterAdvice(){
System.out.println("这是后置通知……");
}
复制代码
3.4 切面类完整代码
/*切面类(通知类)*/
@Component//将这个类定义成 Bean
@Aspect//将这个Bean定义为切面
public class MyAdvice {
//切点方法必须是private,无返回值,无参数
@Pointcut(value = "execution(* com.bighorn.*.*Dao.*(..))")
private void pointCut() {
}
//使用切入点引用
@Before("MyAdvice.pointCut()")
public void beforeAdvice() {
System.out.println("这是前置通知……");
}
//使用切入点表达式
@After(value ="execution(* com.bighorn.*.*Dao.*(..))")
public void afterAdvice(){
System.out.println("这是后置通知……");
}
}
复制代码
4、启用 @AspectJ 注解支持
在 Spring 的配置类中 使用@AspectJ 注解 , 开启 AspectJ 的自动代理 ,使用 @ComponentScan 注解开启注解扫描。
/*Spring核心配置类*/
@Configuration
@ComponentScan("com.bighorn") //开启注解扫描
@EnableAspectJAutoProxy //开启 AspectJ 的自动代理
public class SpringConfig {
}
复制代码
5、编写运行程序
public static void main(String[] args) throws SQLException {
//获取配置类初始化容器
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
//从容器中获取UserDao对象
UserDao userDao = context.getBean(UserDao.class);
//调用userDao的方法
userDao.add();
userDao.delete();
userDao.update();
userDao.select();
}
复制代码
运行结果如下,可以发现对每个方法都进行的加强:前置通知和后置通知

写在后面:beers:
感谢观看啦
有什么不足,欢迎指出哦
1万+



被折叠的 条评论
为什么被折叠?



