【小家Spring】Spring AOP的多种使用方式以及神一样的AspectJ-AOP使用介绍(下)

简介: 【小家Spring】Spring AOP的多种使用方式以及神一样的AspectJ-AOP使用介绍(下)

AspectJ的织入方式及其原理概要


对于织入这个概念,可以简单理解为aspect(切面)应用到目标函数(类)的过程。对于这个过程,一般分为动态织入和静态织入,动态织入的方式是在运行时动态将要增强的代码织入到目标类中,这样往往是通过动态代理技术完成的,如Java JDK的动态代理(Proxy,底层通过反射实现)或者CGLIB的动态代理(底层通过继承实现),Spring AOP采用的就是基于运行时增强的代理技术,这点另一篇博文已经有分析了,这里主要重点分析一下静态织入。


ApectJ采用的就是静态织入的方式。ApectJ主要采用的是编译期织入,在这个期间使用AspectJ的acj编译器(类似javac)把aspect类编译成class字节码后,在java目标类编译时织入,即先编译aspect类再编译目标类。


image.png


关于ajc编译器,是一种能够识别aspect语法的编译器,它是采用java语言编写的,由于javac并不能识别aspect语法,便有了ajc编译器,注意ajc编译器也可编译java文件。为了更直观了解aspect的织入方式,我们打开前面案例中已编译完成的HelloWord.class文件,反编译后的java代码如下:


//编译后织入aspect类的HelloWord字节码反编译类
public class HelloWord {
    public HelloWord() {
    }
    public void sayHello() {
        System.out.println("hello world !");
    }
    public static void main(String[] args) {
        HelloWord helloWord = new HelloWord();
        HelloWord var10000 = helloWord;
   try {
        //MyAspectJDemo 切面类的前置通知织入
        MyAspectJDemo.aspectOf().ajc$before$com_zejian_demo_MyAspectJDemo$1$22c5541();
        //目标类函数的调用
           var10000.sayHello();
        } catch (Throwable var3) {
        MyAspectJDemo.aspectOf().ajc$after$com_zejian_demo_MyAspectJDemo$2$4d789574();
            throw var3;
        }
        //MyAspectJDemo 切面类的后置通知织入 
        MyAspectJDemo.aspectOf().ajc$after$com_zejian_demo_MyAspectJDemo$2$4d789574();
    }
}


显然AspectJ的织入原理已很明朗了,当然除了编译期织入,还存在链接期(编译后)织入,即将aspect类和java目标类同时编译成字节码文件后,再进行织入处理,这种方式比较有助于已编译好的第三方jar和Class文件进行织入操作,由于这不是本篇的重点,暂且不过多分析,掌握以上AspectJ知识点就足以协助理解Spring AOP了

Spring AOP的优点


Spring AOP 与ApectJ 的目的一致,都是为了统一处理横切业务,但与AspectJ不同的是,Spring AOP 并不尝试提供完整的AOP功能(即使它完全可以实现),Spring AOP 更注重的是与Spring IOC容器的结合,并结合该优势来解决横切业务的问题,因此在AOP的功能完善方面,相对来说AspectJ具有更大的优势


同时,Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),因此Spring很机智回避了这点,转向采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ(静态织入)最根本的区别。


在AspectJ 1.5后,引入@Aspect形式的注解风格的开发,Spring也非常快地跟进了这种方式,因此Spring 2.0后便使用了与AspectJ一样的注解。请注意,Spring 只是使用了与 AspectJ 5 一样的注解,但仍然没有使用 AspectJ 的编译器,底层依是动态代理技术的实现,因此并不依赖于 AspectJ 的编译器


再说区别和联系


AspectJ


AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件(只是我们Spring一般只用到它的注解,其余都是Spring自己实现的)。

Spring AOP


Spring提供了四种类型(说三种也对)的Aop支持:


1.基于经典的SpringAOP


      1.使用ProxyFactoryBean创建Bean。显然已经过时了,因为每个Bean你都使用它包装一下,麻烦


     2.引入自动代理创建器。如:AbstractAutoProxyCreator的所有子类,实现有多种。(EnableAspectJAutoProxy注解驱动原理就是它)

             前置通知:org.springframework.aop.MethodBeforeAdvice


             后置通知:org.springframework.aop.AfterReturningAdvice


             异常通知:org.springframework.aop.ThrowsAdvice


             环绕通知:org.aopalliance.intercept.MethodInterceptor (注意这个是aopalliance包下的接口,Spring提供实现类非常之多,比如:MethodBeforeAdviceInterceptor(包装了MethodBeforeAdvice),CacheInterceptor等等非常多)


2.纯POJO切面


      这个方式也就比较古老了,纯基于xml,简单例子如下:



  <-- Spring Aop的命名空间可以将纯POJO转换为切面,实际上这些POJO只是提供了满足切点的条件时所需要调用的方法,但是,这种技术需要XML进行配置,不能支持注解  -->
  <bean id="pojoAdvice" class="com.njust.learning.spring.pojoaop.PojoAdvice"></bean>
    <aop:config>
        <aop:pointcut id="p" expression="execution (* *.add(..))"/>
        <aop:aspect ref="pojoAdvice">
            <aop:before method="before" pointcut-ref="p"></aop:before>
            <!--通过设置returning来将返回值传递给通知-->
            <aop:after-returning method="after" pointcut-ref="p" returning="returnval"/>
            <aop:around method="around" pointcut-ref="p"/>
            <!--通过设置returning来将异常对象传递给通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="p" throwing="e"/>
        </aop:aspect>
    </aop:config>


3.@ASpectJ注解驱动的切面


  1. 需要注意的是,Spring只使用到了它的注解功能,并不使用它的核心功能。核心解析功能由Spring自己实现的


@Aspect
public class HelloAspect {
    @Pointcut("execution(* com.fsx.service.*.*(..)) ")
    public void point() {
    }
    @Before("point()")
    public void before() {
        System.out.println("this is from HelloAspect#before...");
    }
    @After("point()")
    public void after() {
        System.out.println("this is from HelloAspect#after...");
    }
    @AfterReturning("point()")
    public void afterReturning() {
        System.out.println("this is from HelloAspect#afterReturning...");
    }
    @AfterThrowing("point()")
    public void afterThrowing() {
        System.out.println("this is from HelloAspect#afterThrowing...");
    }
    // 此处需要注意:若写了@Around方法,那么最后只会执行@Around和@AfterReturning 其它的都不会执行
    //@Around("point()")
    //public void around() {
    //    System.out.println("this is from HelloAspect#around...");
    //}
}


4.注入式AspectJ切面(其实与Spring并无多大的关系,这个就是使用AspectJ这个框架实现Aop编程) 需用用到AspectJ自己的编译器,因此其实也可以说这个不属于Spring的

  1. 这种方式上面已经做了案例了,此处忽略(使用较少,但Spring也给与了支持)


联系

我们借助于Spring Aop的命名空间可以将纯POJO转换为切面,实际上这些POJO只是提供了满足切点的条件时所需要调用的方法,但是,这种技术需要XML进行配置,不能支持注解


所以spring借鉴了AspectJ的切面,以提供注解驱动的AOP,本质上它依然是Spring基于代理的AOP,只是编程模型与AspectJ完全一致,这种风格的好处就是不需要使用XML进行配置(XML方式已经淘汰嘛,哈哈)


最后

博主希望通过本文,让读者能够了解到Spring AOP和AspectJ的区别与联系。


相关文章
|
2月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
2月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
74 5
|
2月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
78 8
|
2月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
2月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
49 5
|
2月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
50 4
|
3月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
57 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
2月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
45 1
|
2月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
46 0
|
3月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
65 0

热门文章

最新文章