跪拜 Guibai
← All articles
Android · Architecture

AspectJ Bytecode Weaving Replaces Boilerplate Network Checks on Android

By 雨白 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Android projects accumulate cross-cutting checks—network, permissions, logging—that bloat every screen. Compile-time weaving with AspectJ removes that duplication at the bytecode level, keeping hand-written code focused on business logic while the injected advice handles the guard. The cost is a more complex build and an indirection layer that shows up in decompiled output and stack traces.

Summary

A single `@NetworkCheck` annotation, processed by an AspectJ `@Around` advice, intercepts method execution and inspects `ConnectivityManager` before the original body runs. The advice extracts a `Context` from the target object—Activity, View, or Fragment—and either shows a toast and returns null on disconnection or calls `joinPoint.proceed()` to continue. Configuration requires the freefair post-compile-weaving Gradle plugin, an AspectJ runtime dependency, and pointing `AjcWeave` at the platform's `android.jar`.

Decompiling the release APK with jadx confirms the transformation: the original method body is replaced by a synthetic call into a generated static method that wraps the advice. The real business logic gets extracted into a separate `_aroundBody0` method, while the advice method performs the context resolution and network gating before delegating back. This is pure compile-time bytecode manipulation, not runtime reflection.

Beyond network gating, the same pattern applies to permission checks, automatic event tracking, and method-level logging—any cross-cutting concern that would otherwise scatter identical boilerplate across a codebase. The trade-off is longer build times and an extra hop when debugging stack traces.

Takeaways
Annotating a method with `@NetworkCheck` triggers AspectJ to weave a connectivity check before the method executes, with no changes to the original callback.
Configuration requires the `io.freefair.android.aspectj.post-compile-weaving` Gradle plugin, `aspectjrt` as a runtime dependency, and the platform's `android.jar` on the AjcWeave bootclasspath.
The `@Around` advice extracts a `Context` from the join point's target—supporting Activity, View, and optionally Fragment—and calls `ConnectivityManager` to decide whether to proceed or show a toast.
Decompiling the release APK shows the original method replaced by a synthetic call; business logic moves to a `_aroundBody0` static method, and the advice lives in a separate `_aroundBody1$advice` method.
Configuration cache must be disabled in `gradle.properties` because the freefair AspectJ weaving task does not yet support it.
The same AOP approach extends to permission checks, automatic event reporting, and method-level logging without scattering boilerplate across the codebase.
Conclusions

Bytecode weaving sidesteps the runtime overhead and fragility of reflection-based proxies, but it shifts complexity to the build pipeline—developers must understand what the ajc compiler generates to debug effectively.

The decompiled output reveals that AspectJ does not merely wrap methods; it restructures them into static helpers, which can complicate stack traces and confuse tools that expect original method signatures.

Disabling Gradle configuration cache is a non-trivial concession for larger projects where cache misses already slow down CI, making the build-time cost of AOP more than just the weaving step itself.

Concepts & terms
Aspect-Oriented Programming (AOP)
A programming paradigm that separates cross-cutting concerns (like logging, security, or network checks) from core business logic by injecting behavior at defined join points, typically at compile time, load time, or runtime.
AspectJ
A seamless extension to Java and Kotlin that implements AOP through compile-time bytecode weaving. It uses annotations like `@Aspect`, `@Pointcut`, and `@Around` to define where and how additional code is inserted into existing methods.
Bytecode Weaving
The process of modifying compiled `.class` files after initial compilation to inject cross-cutting code. AspectJ's ajc compiler performs this during the build, altering method bodies before they are packaged into an APK.
Join Point / Pointcut
In AOP, a join point is a specific execution point in a program (e.g., a method call). A pointcut is an expression that selects a set of join points—here, any method annotated with `@NetworkCheck`.
From the discussion
Featured comments
KawaNull 1 likes

Before, I was just like you, but now I wouldn't really recommend using this thing. Young man, give it up.

雨白

AspectJ, you mean, or something else?

KawaNull  → 雨白  · 1 likes

Yeah, I used to use AspectJ for handling permissions and event tracking too, but not anymore. Just using a singleton is more practical—check the method reference and you immediately know where it is.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗