Spring AOP
AOP
AOP是什么
AOP的应用场景
Spring AOP和AspectJ
AOP,Spring AOP,AspectJ三者之间的关系
Spring AOP的底层技术
Spring AOP的一些基本概念
Spring AOP案例
AOP
AOP是什么
是一种面向切面编程的思想,传统的OOP开发中的代码逻辑是自上而下的,而这些过程会产生一些横切性问题,这些横切性的问题和我们的主业务逻辑关系不大,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。AOP是处理一些横切性问题,AOP的编程思想就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。使代码的重用性和开发效率更高。
AOP的应用场景
日志记录
权限验证
事务管理
Spring AOP和AspectJ
AOP,Spring AOP,AspectJ三者之间的关系
AOP是一种思想。
SpringAop、AspectJ都是AOP的实现,Spring AOP有自己的语法,但是语法复杂,所以Spring AOP借助了AspectJ的注解,但是底层实现还是自己的。
Spring AOP提供了两种编程风格
@AspectJ support ------------>利用aspectj的注解
Schema-based AOP support ----------->xml aop:config 命名空间复制
Spring AOP的底层技术
使用了动态代理,包含jdk动态代理和Cglib动态代理。并且在初始化时期织入。
Spring AOP的一些基本概念
aspect:切面
在类上声明 @Aspect
交给Spring管理 @Component
pointcut:切点
连接点的集合
告诉通知连接点在哪里
切点表达式决定joinpoint的数量
joinpoint:连接点
目标对象的方法
要关注和增强的方法,也就是我们要作用的点。
weaving:织入,把代理逻辑加入到目标对象上的过程
target:目标对象(原始对象)
aop proxy:代理对象,包含了原始对象的代码和增加后的代码的那个对象
advice:通知(位置 + logic)
advice通知类型
Before 连接点执行之前,
After 连接点正常执行之后
After throwing 执行抛出异常的时候
After finally 无论连接点是正常退出还是异常退出,都执行
Around advice 围绕连接点执行,例如方法调用。这是最有用的切面方式。around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速建议的方法执行。
Spring AOP案例
创建maven项目,并引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
</dependencies>复制
使用Java Config启用@AspectJ支持
package com.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {
}复制
声明一个切面类
package com.example.config;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 声明一个切面
* 此切面一定要交给Spring管理
*/
@Aspect
@Component
public class TxAspect {
@Pointcut("execution(* com.example.dao.*.*(..))")
public void pointCut(){
}
@After("com.example.config.TxAspect.pointCut()")
public void after(){
System.out.println("after...");
}
/**
* before通知,在pintCut切入点前执行
*/
@Before("com.example.config.TxAspect.pointCut()")
public void before(){
System.out.println("before...");
}
@AfterThrowing("com.example.config.TxAspect.pointCut()")
public void doRecoveryActions(){
System.out.println("异常");
}
}复制
新建dao接口和IndexDao类
package com.example.dao;
public interface Index {
void query();
}复制
package com.example.dao;
import org.springframework.stereotype.Component;
@Component
public class IndexDao implements Index {
@Override
public void query(){
System.out.println("dao----query");
System.out.println(1/0);
}
}复制
新建测试类
package com.example.test;
import com.example.config.AppConfig;
import com.example.dao.Index;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Index dao1 = context.getBean(Index.class);
dao1.query();
}
}复制
运行结果如下