对于 Spring AOP 的了解
AOP 为 Aspect Oriented Programming 的缩写:面向切面编程,AOP 是 OOP 的连续 AOP 并不是一种技术,只是一种思维,即面向切面编程的思维
在开发中日志的应用时很频繁的,上面就来用 AOP 来解决一下开发中的日志输入的问题
@Service
public class TestService {public int sum(int a ,int b){System.out.println("参数为:"+a+"+"+b);
int sum = a+b;
System.out.println("后果为:"+sum);
return sum;
}
}
@Autowired
private TestService testService;
@Test
void contextLoads() {testService.sum(1,2);
}
参数为:1+2
后果为:3
在不应用 aop 的状况下,咱们打印日志要这样写,这样写的话就是业务代码跟日志输入都写在了一起,使得代码冗余,而且在前面如果说,不须要将参数输入到日志中了,这样须要一个类一个类的批改代码,工作量时很大的
AOP 就很不便简略的解决了这个问题
AOP 的了解
这是之前的日志输入办法
这个时应用 AOP 的日志输入办法
其实 AOP,面向切面很好了解,就是在一个类上横切一刀,将咱们须要的代码切入,并且不影响之前代码的执行,实现理解耦
AOP 的长处
1、面向切面编程使得每个关注点都集中于一个中央而不是扩散在多处代码中,便于前期的对立保护治理。
2、服务模块更简洁,它们只蕴含次要关注点,而主要关注点的代码被转移到切面中了。
3、对原办法进行办法加强,且不影响原办法的失常应用。
4、应用简略可插拔的配置,在理论逻辑执行之前、之后或四周动静增加横切关注点。
AOP 的术语
名称 | 形容 |
---|---|
切面(Aspect) | 切面是告诉和切点的联合 |
告诉(Advice) | 告诉定义了切面是什么以及何时应用。除了形容切面要实现的工作,告诉还解决了何时执行这个工作的问题 |
切点(Pointcut) | 切点定义了在何处工作,也就是真正被切入的中央,也就是在哪个办法利用告诉 |
连接点(Join point) | 连接点是在利用执行过程中可能插入切面的一个点 |
引入(Introduction) | 引入让一个切面能够申明被告诉的对象实现了任何他们没有真正实现的额定接口,而且为这些对象提供接口的实现 |
织入(Weaving) | 织入是把切面利用到指标对象并创立新的代理对象的过程 |
其中在 Spring 中有 5 中告诉类型
名称 | 形容 |
---|---|
前置告诉(Before) | 在指标办法被调用之前调用 |
后置告诉(After) | 在指标办法实现之后调用 |
返回告诉(After-returning) | 在指标办法胜利执行之后调用 |
异样告诉(After-throwing) | 在指标办法抛出异样后调用 |
盘绕告诉(Around) | 告诉包裹了被告诉的办法,可同时定义前置告诉和后置告诉 |
SpringBoot 实现 AOP
- 新建一个 SpringBoot 我的项目
-
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
-
AOP 的实现须要进行配置,在 Spring 中应用的时 xm 的形式进行配置,然而在 SpringBoot 中勾销了 xml,改为应用了配置类进行配置
package com.mango.Aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * @Author: * @Date: * @Component 被 Spring 治理
*/
@Component
@Aspect
public class TestAspect {
/**
* @Pointcut("execution(* com.mango.service.*.*(..))")
* execution 括号中的是一个表达式,外表在 com.mango.service 这个包下的所有类所有办法所有返回值,所有参数
* 申明切入点
* execution 关键字
* * com.mango.service. *. * (..) )
* 所有的返回值 包名 所有类 所有办法 所有的参数
*/
@Pointcut("execution(* com.mango.service.*.*(..))")
public void pointcut(){}
/**
* @Before("pointcut()") 前置告诉,在切入点之前
* @param joinPoint 能够通过他来获取办法以及参数
*/
@Before("pointcut()")
public void before(JoinPoint joinPoint){Object [] args = joinPoint.getArgs();
for (Object arg : args) {System.out.println("参数为:"+arg);
}
}
/**
* @param joinPoint
* @param returnValue
* @AfterReturning(value = "pointcut()",returning = "returnValue")
* returning 获取返回值
*/
@AfterReturning(value = "pointcut()",returning = "returnValue")
public void returning(JoinPoint joinPoint,Object returnValue){System.out.println("后果为:"+returnValue);
}
}
@Service
public class TestService {
public int sum(int a ,int b){
int sum = a+b;
return sum;
}
}
@SpringBootTest
class SpringbootAopApplicationTests {
@Autowired
private TestService testService;
@Test
void contextLoads() {testService.sum(1,2);
}
}
参数为:1
参数为:2
后果为:3
其余的 After 之类的就不再举例了,用法都是一样的
这样就是实现了 AOP,是不是很简略,其实 AOP 的应用时很简略的,重要的是了解 AOP 的这种思维
### AOP 的使用的技术
SpringAOP 应用了两种代理机制,一种是基于 JDK 的动静代理,另一种是基于 CGLib 的动静代理,之所以须要两种代理机制,很大水平上是因为 JDK 自身只提供基于接口的代理,不反对类的代理。** 切面植入的办法:**
编译期织
类装载期织入
动静代理织入 在运行期为指标类增加加强生成子类的形式,Spring AOP 采纳动静代理织入切面
AOP 有两种次要的框架,SpringAOP 和 AspectJ