面向切面编程思维(AOP)
AOP可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用
spring aop的作用
使用spring aop可以将项目中的非核心代码抽取出来整合到一起封装到一个可重用的模块中,减少业务代码中的非核心代码,达到解耦合的目的。
spring aop的使用场景
- 日志记录:在系统中记录日志是非常重要的,可以使用AOP来实现日志记录的功能,可以在方法执行前、执行后或异常抛出时记录日志。
- 事务处理:在数据库操作中使用事务可以保证数据的一致性,可以使用AOP来实现事务处理的功能,可以在方法开始前开启事务,在方法执行完毕后提交或回滚事务。
- 安全控制:在系统中包含某些需要安全控制的操作,如登录、修改密码、授权等,可以使用AOP来实现安全控制的功能。可以在方法执行前进行权限判断,如果用户没有权限,则抛出异常或转向到错误页面,以防止未经授权的访问。
- 性能监控:在系统运行过程中,有时需要对某些方法的性能进行监控,以找到系统的瓶颈并进行优化。可以使用AOP来实现性能监控的功能,可以在方法执行前记录时间戳,在方法执行完毕后计算方法执行时间并输出到日志中。
- 异常处理:系统中可能出现各种异常情况,如空指针异常、数据库连接异常等,可以使用AOP来实现异常处理的功能,在方法执行过程中,如果出现异常,则进行异常处理(如记录日志、发送邮件等)。
- 缓存控制:在系统中有些数据可以缓存起来以提高访问速度,可以使用AOP来实现缓存控制的功能,可以在方法执行前查询缓存中是否有数据,如果有则返回,否则执行方法并将方法返回值存入缓存中。
- 动态代理:AOP的实现方式之一是通过动态代理,可以代理某个类的所有方法,用于实现各种功能。
spring aop的底层实现
spring aop的底层使用的是动态代理技术有JDK动态代理和cglib动态代理,当需要进行代理的类有接口时使用的JDK动态代理技术,反之则是使用cglib动态代理技术
spring aop 的使用(使用aspectj)
1,添加aop所需的依赖
<!-- spring-aspects会帮我们传递过来aspectjweaver -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.6</version>
</dependency>
2,构建切面类
-
创建一个类并且添加@Aspect
-
在类中声明非核心代码 并且加上对应的注解
- 前置通知:在被代理的目标方法前执行 @Before
- 返回通知:在被代理的目标方法成功结束后执行 @AfterReturning
- 异常通知:在被代理的目标方法异常结束后执行 @AfterThrowing
- 后置通知:在被代理的目标方法最终结束后执行 @After
- 环绕通知:使用try...catch...finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置 @Around
-
在注解中写入切点表达式
-
开启aspectj的支持
-
xml方式 <aop:aspectj-autoproxy />
-
配置类方式
-
//@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
@SpringJUnitConfig(value = {MyConfig.class})
public class AopTest {
@Autowired
private Calculator calculator;
@Test
public void testCalculator(){
calculator.add(1,1);
}
}
获取通知信息
jointpont接口
-
要点1:JoinPoint 接口通过 getSignature() 方法获取目标方法的签名(方法声明时的完整信息)
-
要点2:通过目标方法签名对象获取方法名
-
要点3:通过 JoinPoint 对象获取外界调用目标方法时传入的实参列表组成的数组
-
要点1:JoinPoint 接口通过 getSignature() 方法获取目标方法的签名(方法声明时的完整信息)
-
要点2:通过目标方法签名对象获取方法名
-
要点3:通过 JoinPoint 对象获取外界调用目标方法时传入的实参列表组成的数组
方法返回值
在返回通知中,通过@AfterReturning注解的returning属性获取目标方法的返回值!
异常对象捕捉
在异常通知中,通过@AfterThrowing注解的throwing属性获取目标方法抛出的异常对象
切点表达式
AOP切点表达式(Pointcut Expression)是一种用于指定切点的语言,它可以通过定义匹配规则,来选择需要被切入的目标对象。
格式 1,固定格式execution
2,方法访问修饰符
3,方法返回值
4,指定包的地址
5,指定类的名称
6,方法参数