我刚入行时,Struts还有一定市场,公司招聘简介上随处可见它的信息。不过,如韩非解老所言:固定理有存亡,有生死,有盛衰。夫物之一存一亡,乍生乍死,初盛而后衰者,不可谓常。没多久,新锐之星Spring携利刃,如秦军铁骑般势如破竹,攻城略地,很快便占据互联网的半壁江山。见此情形,我也立马调转枪头,迎后而弃前,如浮萍一般茫茫然而随波逐流。然此一行,荣少辱多。如今混市数载,却对横行霸市之“恶霸”鲜有了解,实在令人咋舌。
犹记几年前,我决心研读Spring源码,但终是雾里看花,少有成绩。自觉原因有三:一曰能力不足,难以为继;二曰缺乏毅力,不肯坚持;三曰镪利吝啬,自孤自傲。好在苍天庇佑,派了一位良师益友时刻相伴。他不断鼓励我坚持目标,并耐心解答我学习过程中遇到的各种问题。在他的帮助下,我对Spring有了全新的认识。对其恩情,我无以为报,唯有来世结草衔环,甘为牛马。书归正传,今天我主要想跟大家分享一下自己对Spring AOP的理解。
AOP,英文全称为:Aspect-Oriented Programming,它是一种编程思想,用于将程序中的横切关注点(如事务、日志)从业务逻辑代码中分离出来,以提高代码的可重用性和可维护性。Spring框架对其进行了实现。在Spring中AOP是通过代理模式实现的,即在运行时动态的生成一个代理,这个代理类会拦截目标对象的方法调用,并在方法执行前后添加响应的横切逻辑。下面就看一下如何使用Spring的AOP功能(下面的代码是基于SpringBoot开发的,所以会直接讲解AOP的开发步骤):
- 在SpringBoot启动类SpringTransactionApplication上新增注解@EnableAspectJAutoPr-oxy,代码如下所示:
import org.com.chinasofti.springtransaction.service.TransferService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import java.math.BigDecimal;
@SpringBootApplication
@EnableAspectJAutoProxy
// @EnableTransactionManagement
public class SpringTransactionApplication {
public static void main(String[] args) {
// SpringApplication.run(SpringTransactionApplication.class, args);
// 下面这段逻辑,可以根据需要新增
TransferService transferService = (TransferService) SpringApplication.run(SpringTransactionApplication.class, args).getBean(TransferService.class);
transferService.check("jack", "tom", BigDecimal.valueOf(100));
}
}
- 编写配置类,该配置类中会指定两个元素:切入点(下述代码中使用@Pointcut注解的方法)、切面(下面代码中使用@Before\@Around\@After注解的方法,切面中要指定一个切入点,所以可以看到在这些注解的后面有一对小括号,里面指定了使用@Pointcut注解修饰的方法,这样在后面调用需要执行切面逻辑的目标方法时,这些切面方法就会先一步调用或者在目标方法调用后调用),具体代码如下所示:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 环绕增强开始!!
* 开始增强!!
* 校验开始
* 校验中||...........
* 一场执行
* 结束增强!!
* 环绕增强结束!!
*/
@Aspect
@Component
public final class CustomerAspect {
@Pointcut("execution(* org.com.chinasofti.springtransaction.service.*.*(..))")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("开始增强!!");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) {
System.out.println("环绕增强开始!!");
Object result = null;
try {
result = joinPoint.proceed();
} catch (Throwable e) {
}
System.out.println("环绕增强结束!!");
return result;
}
@After("pointcut()")
public void end() {
System.out.println("结束增强!!");
}
@AfterReturning("pointcut()")
public void afterReturning() {
System.out.println("返回之后执行");
}
@AfterThrowing("pointcut()")
public void afterThrowing() {
System.out.println("异常执行");
}
}
这里我们要注意一下这些切面的执行顺序:@Around注解修饰的方法在这三个切面中会最先调用,之后是@Before注解修饰的方法,接着执行目标方法代码,然后执行@After注解修饰的方法,最后再次执行@Around注解修饰的方法。
到这里,不禁想起了曾经的一场面试,当时面试官这样问:工作过程中有用过Spring AOP吗?AOP是什么?你觉得它有那些作用?Spring AOP的有点有哪些?
本来就毫无准备,听到这我彻底慌了,就想着赶紧搪塞过去,张嘴就是:用过。AOP就是一个切面编程,用于处理事务、日志等。它的主要作用就是解耦
……
一阵沉默过后,面试官首先打破了沉寂,你有没有什么想了解的?
……
现在再看这个面试题,我绝对不会那样回答,而这样回答。欢迎大家检查,如果有不对的地方,还请大家多多指教。
AOP是一种编程思想,用于将程序中的横切关注点(如事务、日志)从业务逻辑代码中分离出来,以提高代码得可重用性和可维护性。Spring框架对其进行了实现。在Spring中AOP是通过代理模式实现的,即在运行时动态的生成一个代理,这个代理类会拦截目标对象的方法调用,并在方法执行前后添加响应的横切逻辑。Spring AOP的作用主要有以下几点:
- 提高代码的可重用性和可维护性:通过将横切关注点与业务逻辑代码分离,使得业务逻辑代码更加简洁,便于理解和维护。
- 实现模块之间的解耦:AOP 可以将不同模块之间的依赖关系降低到最低,使得系统更加灵活和可扩展。
- 增强代码的安全性:通过 AOP,可以在不修改原有代码的情况下,对方法进行权限控制、性能监控等操作。
Spring AOP的优点主要有:
- 基于动态代理:Spring AOP 采用 JDK 动态代理和 CGLIB 动态代理两种方式,可以根据需要选择使用。
- 声明式编程:AOP 允许开发者通过配置文件或注解的方式定义切面、切点和通知,无需手动编写繁琐的代码。
- 集成性强:Spring AOP 与 Spring 框架完美集成,可以与其他 Spring 模块无缝协作。
- 丰富的功能:Spring AOP 提供了丰富的功能,包括连接点管理、通知类型、切入点表达式等。