AOP增强:AJc编译技术解析

适合有一定spring基础的人阅读。

ajc编译

此方法是再编译阶段进行的增强,大家先看效果,后面我会讲解原理及使用。

演示

首先来介绍一下大家可能会比较陌生的吧,ajc编译,大家看到这个可能不知道是个什么玩意儿,话不多说,先看看效果。

我们先来定义两个类,用来增强的类和目标类。

目标类:

java 复制代码
@Service // 添加该类的bean到容器中,方便后续的测试,不加也可以增强(后续会将)
public class MyService {
    // 使用日志来打印,方便观察结果,不要使用@Slf4j注解,该增强方法不兼容,编译会报错
    private static final Logger log = LoggerFactory.getLogger(MyService.class);
    
    public void foo() {
        log.info("我是目标方法!");
    }
}

增强类:

java 复制代码
@Aspect// 不用加@Component后续会讲增强原理
public class MyAspect {
    // 作用同上
    private static final Logger log = LoggerFactory.getLogger(MyAspect.class);
    // 通知方法,匹配我上面的目标方法,根据自身情况改变
    @Before("execution(* com.huang.service.MyService.*())")
    public void before() {
        log.info("before");
    }
}

启动类:

java 复制代码
@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        // 获取springboot的容器对象
        ConfigurableApplicationContext run = SpringApplication.run(Main.class, args);
        // 从容器中获得目标bean
        MyService service = run.getBean(MyService.class);
        // 打印查看获取到的bean类型,是原始类型还是代理
        System.out.println(service.getClass());
        // 运行方法,查看是否被增强
        service.foo();
    }
}

运行截图奉上:

从图中我们可以看到,我们的 MyService 类并没有被代理,但是foo()方法被增强了。

其实这个是使用了Aspectj的编译器进行的增强,把我们的MyService的类进行了改写(后续会讲怎么使用的)。

找到项目中MyService的字节码文件打开(idea会自动进行反编译)

可以看到日志输出之前调用before()方法

总结

我们的增强类没有加@Component,并不是由spring进行的管理,而是由Aspectj的编译器来读到这个切面,根据这个切面来进行增强,所以我们不需要使用spring也可以达到增强的效果。

修改后的启动类:

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 直接new对象
        MyService myService = new MyService();
        // 调用方法
        myService.foo();
    }
}

运行结果:

从运行结果中可以看到, MyService类依然被增强了

使用

我们需要在项目中添加一个编译器插件,maven代码如下:

xml 复制代码
<build>
    <plugins>
        <!-- 编译时织入插件 -->
        <plugin>
            <groupId>dev.aspectj</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.14</version>
            <configuration>
                <complianceLevel>8</complianceLevel> <!-- Java 版本 -->
                <source>8</source>
                <target>8</target>
                <showWeaveInfo>true</showWeaveInfo>
                <forceAjcCompile>true</forceAjcCompile>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

这里我只给出了编译器插件的部分,如果需要使用其他的依赖,请自行添加依赖。

如果添加了之后运行没有被增强,可以先使用maven编译之后再运行

请不要使用@Slf4j注解,Aspectj编译器并不支持

此方法可以增强静态方法,这是代理所不能做到

相关推荐
非洲农业不发达5 小时前
windows终端体验大升级,让你拥有macos级别的美化
前端·后端
妙码生花5 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十七):登录接口完善,登录页接口整合,解决跨域
前端·后端·ai编程
SamDeepThinking5 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
shepherd1115 小时前
一文带你掌握 LLM、Token、Context、Prompt、RAG、MCP、Skill、Agent 等 AI 核心概念
人工智能·后端·ai编程
狂炫冰美式6 小时前
人均配了AI, 为什么公司还是没变快? 🤔 本质还是分布式系统问题
前端·后端·架构
她的男孩8 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
爱读源码的大都督8 小时前
Claude Code源码分析(三):为什么系统提示词中需要有tools呢?
前端·人工智能·后端
爱勇宝8 小时前
Claude Code 被曝暗藏“隐形检测”代码:封代理不是最可怕的,可怕的是你根本不知道它在干什么
前端·后端·程序员
ITOM运维行者9 小时前
从零搭建企业级服务器监控体系:踩坑实录与架构设计
前端·后端