Spring + AspectJ

本文介绍Spring框架中AspectJ的两种使用方式及其选择原则,详细讲解了AspectJ的编译期(CTW)和加载期(LTW)织入过程,并通过实例演示了如何配置Maven及META-INF/aop.xml来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • Spring中使用它所集成的AspectJ有两种方式:

    1. 直接完全用AspectJ

    这种已经脱离了Spring,跟它没一分钱关系了。自己定义AspectJ语法的.aj文件

     

    1. 使用@Aspect annotation

    使用,这种更加简单

     

    两种方式如何选择?

     

    1. AspectJ在你的设计中占据很大的角色时,并且你又刚好是用Eclipse来做开发,那么用AspectJ Development Tools AJDTEclipse插件来使用AspectJ语法来定义是最佳选择:它更整洁和简单,因为AspectJ就是为了写切面而开发的语言。
    2. 如果你不是用Eclipse,或者只有少量的切面,在你的应用中并不占主要角色,你就可以选择用annotation,然后在build脚本中加入AspectWeaving部分。

     

    这两种,都会在真正加载时加载Weaving后的class

    它怎么做到的呢?我们看看过实现一个织入过程。

    AspectJ支持两种WeavingCTW(CompileTimeWeaving)LTW(LoadTimeWeaving)

     

    CTW

    在编译时引入AspectJ的编译器,最终的字节码是已经Weaving后的代码。

    1. aspect.aj文件(AspectJ的语言)或者aspect JAVA类带上 @Aspect
    2. mavenant脚本,引入AspectJ的编译器进行编译

     

    LTW

    在加载时引入AspectJ的类加载器,在类加载到JVM时,织入切面。

    1. aspect.aj文件(AspectJ的语言)或者aspect JAVA类带上 @Aspect
    2. 写一个META-INF/aop.xml,指明aspect
    3. 修改应用启动参数,通过设定JVM-javaagent参数引入LTW的织入器类包,以代替JVM默认类加载器

     

    举例

    为方便起见,还是使用之前的Zooannotation代码,参见Spring AOP @Aspect support annotation一文

    CTW很简单,只需要修改.pom即可

    <build>

    <plugins>

    <plugin>

    <groupId>org.codehaus.mojo</groupId>

    <artifactId>aspectj-maven-plugin</artifactId>

    <version>1.4</version>

    <configuration>

    <complianceLevel>1.6</complianceLevel>

    </configuration>

    <executions>

    <execution>

    <goals>

    <goal>compile</goal>

    <goal>test-compile</goal>

    </goals>

    </execution>

    </executions>

    </plugin>

     

    <plugin>

    <artifactId>maven-assembly-plugin</artifactId>

    <configuration>

    <finalName>RunnableTest</finalName>

    <appendAssemblyId>false</appendAssemblyId>

    <descriptorRefs>

    <descriptorRef>jar-with-dependencies</descriptorRef>

    </descriptorRefs>

     

    <archive>

    <manifest>

    <mainClass>com.edi.poc.Zoo</mainClass>

    </manifest>

    </archive>

     

    </configuration>

     

    <executions>

    <execution>

    <id>make-assembly</id>

    <phase>package</phase>

    <goals>

    <goal>assembly</goal>

    </goals>

    </execution>

    </executions>

    </plugin>

    </plugins>

    </build>

     

    为方便起见,我把这个包做了一个可执行jar,叫RunnableTest.jar

    运行mvn clean install后,在target目录找到它,运行如下:

    java -jar RunnableTest.jar

    Dinosaur hall is opened.

    The People Zoo is opened.

    Before method...

    Charge Jack $1.00 for ticket.

    Jack needs to be charged first.

    Dianosaur hall charges Jack $2.00

    Jack visited diano hall.

    After return...

    Dinosaur hall is closed.

    The People Zoo is closed.

     

     

    可以看到完全跟上篇文章中输出一样。

    jad反编译看看包里的Zoo.class

    public Hall enter(Entrant ???, HALL_NAME arg2)

      {

        Object localObject2 = ???;

        Object localObject1;

        Object localObject3 = localObject1; JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, ???, ???, localObject2, localObject3);

        HALL_NAME hallName;

        Entrant e;

        MyAspect.aspectOf().before(localJoinPoint); charge(e);

        return (Hall)this.halls.get(hallName);

      }

    这里的enter方法已然已被Weaving了。

     

    LTW的例子

    我们在src/main/resources/下创建 META-INF/aop.xml

    <aspectj>

        <aspects>

            <aspect name="com.edi.poc.aop.MyAspect"/>

        </aspects>

    </aspectj>

     

    启动时加入-javaagent:<path>/aspectjweaver-1.6.12.jar即可得到同样结果

     

    参考文章:

    http://opoo.org/aspectj-compile-time-weaving/

    http://www.andrewewhite.net/wordpress/2010/03/17/aspectj-annotation-tutorial/

    http://log-cd.iteye.com/blog/562056

     

    本文源码:

    https://github.com/EdisonXu/POC/tree/master/intro-aop

     

### 如何在Spring Boot中集成AspectJ实现AOP功能 要在Spring Boot项目中成功集成AspectJ并实现AOP(面向切面编程),可以按照以下方法操作: #### 依赖管理 为了支持AspectJ的功能,需要引入`aspectjrt`, `aspectjweaver`以及`sprina-aop`库。这些库可以通过Maven或Gradle来管理[^5]。 ```xml <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.7</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 上述配置展示了如何通过Maven的`pom.xml`文件添加必要的依赖项。 #### 配置启用AspectJ 确保在Spring Boot应用启动类上标注了`@EnableAspectJAutoProxy`注解以激活AspectJ代理机制。此注解会自动扫描带有`@Aspect`标记的组件,并将其注册为切面对象[^2]。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` #### 创建切面逻辑 定义一个切面类用于拦截目标方法执行前后的行为。下面是一个简单的例子展示如何记录日志信息[^3]: ```java package com.example.demo.aspects; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Around("execution(* com.example.demo.service.*.*(..))") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); try { return joinPoint.proceed(); } finally { long executionTime = System.currentTimeMillis() - start; logger.info("{} executed in {}ms", joinPoint.getSignature(), executionTime); } } } ``` 这段代码创建了一个名为LoggingAspect的切面,在任何匹配的服务层方法调用时都会触发时间测量和打印日志的操作。 #### 总结 通过以上步骤可以在Spring Boot环境中顺利设置基于Annotation驱动的AspectJ AOP框架。这不仅简化了开发过程中的横切关注点处理方式,还增强了应用程序的整体可维护性和扩展能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值