跳至主要內容

Spring的AOP

ZnyoungJavaSpring

介绍Spring的AOP

AOP(Aspect-Oriented Programming),即面向切面编程,用人话说就是把公共的逻辑抽出来,让开发者可以更专注于业务逻辑开发。

和IOC一样,AOP也指的是一种思想。AOP思想是OOP面向对象(Object-Oriented Programming)的补充。OOP是面向类和对象的,但是AOP则是面向不同切面的。一个切面可以横跨多个类和对象去操作,极大的丰富了开发者的使用方式,提高了开发效率。

常见概念

名词概念解释
切面(Aspect)切面是一个模块化的特性,它包含了一组通知和切点。通知定义了在切点处要执行的代码,而切点则定义了在何处应用通知。切面可以被应用到一个或多个目标对象中。
通知(Advice)通知定义了切面在切点处执行的代码。在Spring AOP中,有五种类型的通知:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。
切点(Pointcut)切点定义了在哪些连接点上应用通知。连接点是在应用执行过程中能够插入切面的点,如方法调用或异常处理。切点使用表达式来匹配连接点。
连接点(Joinpoint)连接点是在应用执行过程中能够插入切面的点,如方法调用或异常处理。连接点是切点的实际实例。
引入(Introduction)引入允许向现有的类添加新的接口和实现。在Spring AOP中,引入是通过一个特殊的通知类型实现的。
织入(Weaving)织入是将切面应用到目标对象并创建新的代理对象的过程。在编译时、加载时或运行时进行织入。
目标对象(Target Object)目标对象是被一个或多个切面所通知的对象。也被称为被通知对象。
代理对象(Proxy Object)代理对象是在目标对象基础上创建的对象,它将切面织入到目标对象中。当客户端通过代理对象调用目标对象时,切面的通知将被触发。
AdvisorAdvisor是将切点和通知组合在一起的对象。它是AOP的基本组成单元。
切面自动代理(Aspect Auto Proxy)切面自动代理是Spring容器自动为目标对象创建代理对象并将切面织入到代理对象中的过程。
AOP代理(AOP Proxy)AOP代理是将切面织入到目标对象中的代理对象。在Spring AOP中,有两种类型的AOP代理:JDK动态代理和CGLIB代理。

如何实现

实现时机

参考Bean的初始化流程。从Bean的初始化流程中来讲,Spring的AOP会在bean实例之前的自定义处理的地方,去生成AOP的代理,如AbstractAutoProxyCreator#postProcessBeforeInstantiation代码所示。

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);

    // 创建代理
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

实现原理

Spring AOP 是通过代理模式实现的 ,具体有两种实现方式,一种是基于Java原生的动态代理,一种是基于cglib的动态代理

Spring AOP默认使用标准的JDK动态代理进行AOP代理 。这使得任何接口可以被代理。但是JDK动态代理有一个缺点,就是它不能代理没有接口的类。

所以Spring AOP就使用CGLIB代理没有接口的类。默认情况下,如果一个业务对象没有实现一个接口,就会使用CGLIB。

上次编辑于:
贡献者: 麦正阳