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依赖
 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
    </dependencies>
  1. 配置xml文件,开启注解扫描

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
     http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
        
     <!-- 开启注解扫描 -->
     <context:component-scan basepackage="com.atguigu.spring5.aopanno"></context:component-scan>
    
    

     

  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配置文件中开启生成代理对象

<!-- 开启 Aspect 生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  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

posted @ 2021-11-24 20:12  _图南  阅读(45)  评论(0编辑  收藏  举报