spring AOP 整理


Spring AOP

1 描述Spring AOP

AOP是面向切面编程。通俗的讲就是可以不修改源代码的方式,在主干功能里面添加新功能;将与业务无关,但和业务模块共同调用的东西(例如事务处理,日志管理,权限控制等)封装起来。从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

2 Spring AOP的原理

Spring AOP是基于动态代理。动态代理有两种情况。

第一种是有接口的情况,使用JDK动态代理。

JDK动态代理:调用newProxyInstance方法。

newProxyInstance(ClassLoader loader, 类 interfaces, InvocationHandler h)。

newProxyInstance方法的三个参数:

1 类加载器

2 切入点的接口

3 实现接口InvocationHandler,创建代理对象,写增强的部分

第二种是没有接口,只有类,使用CGLIB动态代理

3 Spring AOP的术语

  • 连接点:类中的那些方法可以被增强

  • 切入点: 实际上真正被增强的方法

  • 通知(增强)

    增强逻辑代码部分

    通知的类型有5种:前置,后置,环绕,异常,最终通知。

  • 切面:是动作,将通知应用放到切入点的过程

4 切入点表达式

作用:表达那个类中的那个方法进行增强

语法结构: execution([权限修饰符] [返回值类型] [][][类全路径] [方法名称] ([参数列表]))

举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强 execution(* com.atguigu.dao.BookDao.add(..))

举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强 execution(* com.atguigu.dao.BookDao.* (..))

举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强 execution(* com.atguigu.dao.. (..))

5 Spring AOP和AspectJ AOP的区别

img

  1. 织入时期不同

Spring AOP是动态织入,即在运行时织入

AspectJ是静态织入,即在编译期额类加载时织入,在编译出来class文件时,字节码就已经被织入。

  • 编译时织入:AspectJ编译器同时加载我们切面的源代码和我们的应用程序,并生成一个织入后的类文件作为输出。

  • 编译后织入:这就是所熟悉的二进制织入。它被用来编织现有的类文件和JAR文件与我们的切面。

  • 加载时织入:这和之前的二进制编织完全一样,所不同的是织入会被延后,直到类加载器将类加载到JVM。

    2. 使用的对象不同
    
  • spring AOP的通知是基于该对象是SpringBean对象才可以

  • AspectJ可以在任何对象上应用通知

6 AspectJ注解实现AOP操作

  1. 导入maven依赖
 
        
            org.springframework
            spring-webmvc
            5.2.9.RELEASE
        

        
            junit
            junit
            4.13
            test
        

        
            org.projectlombok
            lombok
            1.18.20
        

        
            org.aspectj
            aspectjweaver
            1.9.7
        
    
  1. 配置xml文件,开启注解扫描

    <?xml version="1.0" encoding="UTF-8"?>
    
        
     
     
    
    
  2. 创建切入点类,创建通知类,并用注解创建对象,在增强类上添加增强注解@Aspect

    //切入点类
    @Component
    public class User {
     public void add() {
     System.out.println("add.......");
     }
    }
    
    //增强类
    @Component
    @Aspect
    public class UserProxy {
     public void before() {//前置通知
     System.out.println("before......");
     }
    }
    
  3. 在 xml配置文件中开启生成代理对象



  1. 配置不同类型的通知

在增强类的通知方法上面添加通知类型的注解,要加切入点表达式

  • 前置通知:@Before
@Component
@Aspect //生成代理对象
public class UserProxy {
 //前置通知
 //@Before 注解表示作为前置通知
 @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
 public void before() {
 System.out.println("before.........");
 }

  • 后置通知:@AfterReturning
  • 最终通知: @AfterTrowing
  • 环绕通知:@Around

环绕通知的优先级大于前置通知&后置通知

  1. 抽取相同的切入点

将相同的切入点提取出来,在增强注解中使用提取的表达式

//相同切入点抽取
@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")

public void pointdemo() {
}
//使用pointdemo代替切入点表达式

@Before(value = "pointdemo()")
public void before() {
 System.out.println("before.........");
}

  1. 有多个增强类多同一个方法进行增强,设置增强类优先级
  • 在增强类上面添加@Order(数字),数字越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy

8.完全使用注解开发(不需要配置文件)

  • 创建一个配置类
//表明配置类
@Configuration
//开启注解扫描
@ComponentScan(basePackages = {"com.atguigu"})
//开启AspectJ生成代理对象
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}

https://juejin.cn/post/6844903555531276296

https://snailclimb.gitee.io/javaguide-interview/#/./docs/e-1spring?id=_514-spring-ioc-amp-aop

https://blog.csdn.net/a128953ad/article/details/50509437