RepoPilotOpen in app →

spring-projects/spring-framework

Spring Framework

GO

Healthy across the board

  • Last commit today
  • 5 active contributors
  • Distributed ownership (top contributor 48%)
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • Small team — 5 top contributors

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Embed this verdict

[![RepoPilot: GO](https://repopilot.app/api/badge/spring-projects/spring-framework)](https://repopilot.app/r/spring-projects/spring-framework)

Paste into your README — the badge live-updates from the latest cached analysis.

Onboarding doc

Onboarding: spring-projects/spring-framework

Generated by RepoPilot · 2026-05-05 · Source

Verdict

GO — Healthy across the board

  • Last commit today
  • 5 active contributors
  • Distributed ownership (top contributor 48%)
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Small team — 5 top contributors

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

TL;DR

Spring Framework is the foundational Java application framework that provides dependency injection (IoC container), aspect-oriented programming via AspectJ, a full MVC web stack (Spring MVC and Spring WebFlux for reactive/non-blocking), data access abstractions (JDBC, ORM, transactions), and messaging support. It solves the problem of enterprise Java application wiring, cross-cutting concerns, and boilerplate reduction that plain Java EE requires. All other Spring projects (Boot, Security, Data, Cloud) are built on top of this specific repo. Monorepo: each spring-* subdirectory (e.g., spring-core, spring-webmvc, spring-webflux, spring-context, spring-jdbc) is an independent Gradle subproject managed via build.gradle and buildSrc/. buildSrc/src/main/java/org/springframework/build/ contains shared build conventions (ConventionsPlugin.java, JavaConventions.java, CheckstyleConventions.java). framework-docs/ holds AsciiDoc reference documentation and framework-platform/ manages dependency versions.

Who it's for

Java and Kotlin backend engineers who build enterprise applications, microservices, or libraries on the JVM and need a production-grade IoC container, web framework, and transaction/data-access layer. Also for Spring ecosystem contributors who add features or fix bugs that affect every downstream Spring project.

Maturity & risk

One of the most mature Java projects in existence — over 20 years old, tens of thousands of GitHub stars, continuous CI via GitHub Actions (.github/workflows/ci.yml, build-and-deploy-snapshot.yml), and comprehensive test coverage across all modules. The build system is Gradle with JMH microbenchmarks and checkstyle enforcement. Verdict: production-ready at the highest possible level.

Risk is extremely low: the project is backed by Broadcom/VMware's Spring team with multiple active committers, strict DCO enforcement (.github/dco.yml), and milestone/release workflows (.github/workflows/release.yml, release-milestone.yml). The only real risks are occasional breaking changes between major versions (e.g., 5.x → 6.x dropped Java EE in favor of Jakarta EE) and the sheer size making it hard to understand cross-module impacts of a change.

Active areas of work

Active development visible in CI workflows includes snapshot deployments (build-and-deploy-snapshot.yml targeting main), milestone releases, and Antora documentation UI updates (update-antora-ui-spring.yml). The dependency stack shows recent upgrades: io.freefair.aspectj 8.13.1, com.gradleup.shadow 9.2.2, and org.jetbrains.dokka for Kotlin API docs, indicating active Kotlin and AspectJ integration work.

Get running

git clone https://github.com/spring-projects/spring-framework.git cd spring-framework

Check required JDK version

cat .sdkmanrc

If using SDKMAN:

sdk env install

Build the entire framework (skipping docs)

./gradlew build -x javadoc

Build a specific module only

./gradlew :spring-core:build

Run tests for a module

./gradlew :spring-webmvc:test

Daily commands: ./gradlew build # full build with tests ./gradlew test # all tests ./gradlew :spring-webmvc:test # module-specific tests ./gradlew :spring-core:jmh # run microbenchmarks in spring-core

Map of the codebase

  • build.gradle — Root build file that defines all subproject configurations, dependency management, and plugin application — the entry point for understanding the entire multi-module build.
  • buildSrc/src/main/java/org/springframework/build/ConventionsPlugin.java — Applies all shared build conventions (Java, Kotlin, Checkstyle, Testing) across every Spring module — must be understood before modifying any module's build behavior.
  • buildSrc/src/main/java/org/springframework/build/JavaConventions.java — Defines Java compilation settings, source compatibility, compiler flags, and toolchain configuration applied uniformly to all spring-* modules.
  • buildSrc/src/main/java/org/springframework/build/architecture/ArchitectureRules.java — Encodes enforced architectural constraints (package dependencies, layering rules) that prevent architectural drift across the framework modules.
  • buildSrc/src/main/java/org/springframework/build/optional/OptionalDependenciesPlugin.java — Implements the custom 'optional' Gradle dependency configuration used extensively across Spring modules to declare compile-time-only optional dependencies.
  • buildSrc/src/main/java/org/springframework/build/hint/RuntimeHintsAgentPlugin.java — Configures the runtime hints agent used for GraalVM native image compatibility testing — critical for understanding Spring's AOT/native support build pipeline.
  • buildSrc/src/main/java/org/springframework/build/multirelease/MultiReleaseJarPlugin.java — Manages multi-release JAR construction for Java version-specific bytecode (e.g. Java 21 virtual threads support), essential for understanding how Spring ships version-specific code.

How to make changes

Add a new Spring module (spring-* subproject)

  1. Create a new directory named spring-<module> at the repo root and add a <module>.gradle build file that applies the spring-module conventions and declares its dependencies. (build.gradle)
  2. Register the new subproject in settings.gradle (not shown in file list but exists at repo root) so Gradle discovers it as part of the multi-project build. (build.gradle)
  3. Declare any optional compile-time dependencies using the 'optional' configuration provided by the custom plugin. (buildSrc/src/main/java/org/springframework/build/optional/OptionalDependenciesPlugin.java)
  4. Add architecture rules if the new module introduces new inter-package boundaries that must be enforced. (buildSrc/src/main/java/org/springframework/build/architecture/ArchitectureRules.java)
  5. Add the new module to the BOM so consumers can import it without specifying a version. (framework-bom/framework-bom.gradle)

Add a Java-version-specific implementation (multi-release JAR)

  1. Apply the MultiReleaseJarPlugin in the target module's .gradle build file and declare the target Java release version via the MultiReleaseExtension DSL. (buildSrc/src/main/java/org/springframework/build/multirelease/MultiReleaseJarPlugin.java)
  2. Configure the release version using the extension's DSL in the module's build file. (buildSrc/src/main/java/org/springframework/build/multirelease/MultiReleaseExtension.java)
  3. Place the version-specific source files in the generated source set directory (e.g. src/main/java21/) and implement only the APIs that differ from the base version. (buildSrc/src/main/java/org/springframework/build/multirelease/MultiReleaseJarValidateTask.java)

Add GraalVM native image runtime hints for a new feature

  1. Register the hint-producing classes in the module's build file using the RuntimeHintsAgentExtension DSL so the agent instruments those tests. (buildSrc/src/main/java/org/springframework/build/hint/RuntimeHintsAgentExtension.java)
  2. Ensure the RuntimeHintsAgentPlugin is applied to the module (it's applied via ConventionsPlugin for all spring-* modules automatically). (buildSrc/src/main/java/org/springframework/build/hint/RuntimeHintsAgentPlugin.java)
  3. Configure the agent JVM argument provider so test runs inject the -javaagent flag with the correct classpath. (buildSrc/src/main/java/org/springframework/build/hint/RuntimeHintsAgentArgumentProvider.java)

Enforce a new cross-module architectural constraint

  1. Add a new ArchUnit rule in ArchitectureRules defining the forbidden or required dependency relationship between packages or modules. (buildSrc/src/main/java/org/springframework/build/architecture/ArchitectureRules.java)
  2. Register the rule in ArchitectureCheck so it is executed as part of the 'checkArchitecture' Gradle task during the verification phase. (buildSrc/src/main/java/org/springframework/build/architecture/ArchitectureCheck.java)
  3. Verify the rule is wired into the build lifecycle via the plugin's task dependency configuration. (buildSrc/src/main/java/org/springframework/build/architecture/ArchitecturePlugin.java)

Traps & gotchas

  1. .sdkmanrc pins a specific JDK version — building with a different JDK (especially < 17) will fail or produce unexpected results. 2) The framework-platform subproject must be published/available before other modules can resolve their dependencyManagement enforced platform — do not skip it when building subsets. 3) Milestone/snapshot Maven repos are conditionally added based on version string contents (-SNAPSHOT or -), so local version overrides can cause dependency resolution failures. 4) AspectJ compilation (io.freefair.aspectj) requires the ajc compiler on the classpath — the plugin handles this but mixing with standard javac tasks can cause subtle weaving issues. 5) cacheChangingModulesFor 0 and cacheDynamicVersionsFor 0 in resolutionStrategy mean every build hits remote repos — ensure network access or use --offline with a populated cache.

Architecture

Concepts to learn

  • Inversion of Control (IoC) Container — The entire spring-context and spring-beans modules implement IoC — understanding bean lifecycle, scopes, and BeanFactory vs ApplicationContext is prerequisite to modifying any core container code.
  • Aspect-Oriented Programming (AOP) with AspectJ weaving — Spring AOP uses JDK dynamic proxies or CGLIB by default but integrates with compile-time/load-time AspectJ weaving via io.freefair.aspectj — the .aj files in the repo use AspectJ syntax, not plain Java.
  • Reactive Streams backpressure — Spring WebFlux is built on Project Reactor which implements Reactive Streams — understanding Publisher/Subscriber/Subscription and backpressure is essential for modifying any spring-webflux code.
  • CGLIB bytecode proxying — Spring's AOP and @Configuration class processing use CGLIB to subclass beans at runtime — this creates constraints (classes cannot be final, must have no-arg constructors) that affect API design across the whole framework.
  • JMH (Java Microbenchmark Harness) — Performance-sensitive paths in spring-core are benchmarked with JMH via me.champeau.jmh plugin — understanding JMH's warmup/measurement phases is required to write or interpret benchmark results.
  • GraalVM Native Image hints — Spring 6.x added first-class AOT (Ahead-of-Time) compilation support for GraalVM native images — spring-core contains RuntimeHints APIs that tell the native compiler what to keep via reflection/proxy registration.
  • Jakarta EE namespace migration — Spring Framework 6.x migrated from javax.* to jakarta.* packages — any code touching servlet, persistence, or validation APIs must use Jakarta EE 9+ package names, and mixing the two in a single classpath causes hard-to-diagnose runtime failures.

Related repos

  • spring-projects/spring-boot — Auto-configuration layer built directly on top of this repo — most users interact with Spring Framework through Spring Boot.
  • spring-projects/spring-security — Companion security framework that integrates tightly with Spring MVC and WebFlux filter chains defined here.
  • spring-projects/spring-data-commons — Repository abstraction layer that relies on Spring Framework's IoC container and transaction infrastructure.
  • google/guice — Close alternative IoC/DI container in the Java ecosystem — useful for understanding design tradeoffs Spring's container makes.
  • quarkus/quarkus — Modern competing Java framework offering compile-time DI and GraalVM native compilation as an alternative to Spring's runtime model.

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add unit tests for ArchitectureRules.java in buildSrc

The file buildSrc/src/main/java/org/springframework/build/architecture/ArchitectureRules.java defines custom architecture enforcement rules used across the entire Spring Framework build. These rules are critical for maintaining code quality across all subprojects, yet the buildSrc directory shows no corresponding test directory structure. Adding unit tests for ArchitectureCheck and ArchitectureRules would prevent regressions in the enforcement logic itself and serve as living documentation of what architectural constraints are enforced.

  • [ ] Examine buildSrc/src/main/java/org/springframework/build/architecture/ArchitectureRules.java and ArchitectureCheck.java to enumerate all rules (e.g. forbidden imports, package dependency rules)
  • [ ] Create buildSrc/src/test/java/org/springframework/build/architecture/ArchitectureRulesTests.java using JUnit 5
  • [ ] Write tests that create minimal compliant and non-compliant class fixtures and assert that ArchitectureCheck passes or fails appropriately for each rule in ArchitectureRules
  • [ ] Add the testImplementation('org.junit.jupiter:junit-jupiter') dependency to buildSrc/build.gradle if not already present
  • [ ] Verify tests run via ./gradlew :buildSrc:test and pass in CI by checking .github/workflows/ci.yml

Add a dedicated GitHub Actions workflow for buildSrc validation

The buildSrc directory contains custom Gradle plugins (ConventionsPlugin, ArchitecturePlugin, RuntimeHintsAgentPlugin, MultiReleaseJarPlugin, OptionalDependenciesPlugin, etc.) that are foundational to the entire build. Inspecting .github/workflows/ reveals workflows for CI, PRs, snapshots, and releases, but none specifically compiles and tests buildSrc in isolation. A dedicated workflow would catch breaking changes to build logic earlier and faster than running the full build, providing faster feedback for contributors modifying build infrastructure.

  • [ ] Review existing .github/workflows/ci.yml and .github/workflows/build-pull-request.yml to understand the current workflow structure and reuse patterns
  • [ ] Create .github/workflows/verify-buildsrc.yml that triggers on push and pull_request when any file under buildSrc/** changes using paths filter
  • [ ] In the workflow, use the existing .github/actions/prepare-gradle-build/action.yml composite action to set up the environment consistently
  • [ ] Run ./gradlew :buildSrc:check (which includes compileJava, checkstyle, and any tests) as the main step
  • [ ] Add checkstyle validation using buildSrc/config/checkstyle/checkstyle.xml to ensure build source code itself follows project conventions

Refactor MultiReleaseJarPlugin.java to extract validation logic into MultiReleaseJarValidateTask.java

The buildSrc file listing shows both MultiReleaseJarPlugin.java and a separate MultiReleaseJarValidateTask.java, which is a good separation of concerns. However, reviewing common patterns in Gradle plugin implementations, it is likely that MultiReleaseJarPlugin.java still contains inline validation or configuration logic that belongs in MultiReleaseJarValidateTask or MultiReleaseExtension. Consolidating this ensures the task is independently testable, reusable, and consistent with the pattern already established by ArchitecturePlugin/ArchitectureCheck and RuntimeHintsAgentPlugin/RuntimeHintsAgentArgumentProvider. This makes the multi-release JAR feature easier for contributors to understand and modify.

  • [ ] Read `buildSrc/src/main/java/org/springframework/build

Good first issues

  1. Add missing Kotlin coroutine extension tests in spring-webflux — Kotlin makes up 1.18M lines but test coverage of Kotlin-specific suspend function handling in WebFlux's CoRouterFunctionDsl is an area where gaps exist. 2) Improve buildSrc/README.md — it is currently sparse and doesn't document what each convention class does (JavaConventions, CheckstyleConventions, ConventionsPlugin), making it hard for new contributors to understand build customization. 3) Add JMH microbenchmarks for spring-expression (SpEL) parsing and evaluation — the JMH plugin is already wired via me.champeau.jmh but SpEL benchmarks are underrepresented compared to core reflection utilities.

Top contributors

Recent commits

  • 051b096 — Merge branch '7.0.x' (sbrannen)
  • 715d33f — Remove control character from log message in TransportHandlingSockJsService (kzander91)
  • 39ff8e4 — Use String#replace instead of String#replaceAll in tests (sbrannen)
  • 27bdf24 — Use String#replace instead of String#replaceAll where appropriate (shenjianeng)
  • d9ecf94 — Merge branch '7.0.x' (sbrannen)
  • bb51421 — Upgrade to Gradle 9.5 (sbrannen)
  • b35da5b — Merge branch '7.0.x' (sbrannen)
  • 25b8d64 — Fix typo in HttpServiceProxyFactory example (0AndWild)
  • 367a620 — Merge branch '7.0.x' (rstoyanchev)
  • d72da90 — Avoid race in InMemoryWebSession (rstoyanchev)

Security observations

  • Medium · Use of Milestone/Snapshot Maven Repositories — build.gradle. The build configuration conditionally adds 'https://repo.spring.io/milestone' and 'https://repo.spring.io/snapshot' repositories when the version string contains '-' or ends with '-SNAPSHOT'. Milestone and snapshot artifacts are not as rigorously validated as GA releases and may introduce untested or unstable code into the build. Snapshot repositories in particular can serve changing artifacts, creating a non-deterministic build and potential supply-chain risk if the remote repository is compromised. Fix: Restrict snapshot/milestone repository usage to dedicated CI branches or profiles. Verify artifact integrity via checksum verification, and consider using a private artifact proxy (e.g., Nexus, Artifactory) that mirrors and scans external repositories. Ensure GA builds never pull from snapshot/milestone repos.
  • Medium · Resolution Strategy Disables Dependency Caching — build.gradle – configure(allprojects) block. The Gradle resolution strategy sets 'cacheChangingModulesFor 0, seconds' and 'cacheDynamicVersionsFor 0, seconds' globally for all projects and configurations. This means every build re-fetches changing and dynamic dependencies from remote repositories without any caching. This increases the attack surface for supply-chain attacks (e.g., dependency confusion, MITM on artifact downloads) and removes a layer of stability guarantees that caching provides. Fix: Restrict zero-cache settings to CI snapshot builds only. For release and standard developer builds, allow normal caching. Pair this with dependency verification (Gradle's dependency-verification.xml) and checksum/PGP signature validation to detect tampered artifacts regardless of caching policy.
  • Medium · Dependency on Third-Party Gradle Plugins Without Explicit Version Pinning or Verification — build.gradle – plugins block. Several third-party Gradle plugins are declared (e.g., 'io.freefair.aspectj' 8.13.1, 'com.github.bjornvester.xjc' 1.8.2, 'com.gradleup.shadow' 9.2.2, 'me.champeau.jmh' 0.7.2, 'io.spring.nullability' 0.0.11). These plugins are fetched from the Gradle Plugin Portal. Without a Gradle dependency-verification file (verification-metadata.xml), there is no integrity check on these artifacts, creating a supply-chain risk if any plugin is compromised or a version is hijacked. Fix: Enable Gradle dependency verification by running 'gradle --write-verification-metadata sha256,pgp' to generate a verification-metadata.xml file. Commit this file to source control and enforce it in CI. Consider hosting approved plugins in an internal artifact repository.
  • Low · JAR Signing Key Documentation References External URL — SECURITY.md. SECURITY.md references the GPG public key at 'https://spring.io/GPG-KEY-spring.txt' over HTTPS. While HTTPS provides transport security, any consumer verifying JAR signatures must trust the DNS and TLS chain for spring.io. If that URL is compromised or unavailable, signature verification can fail or be bypassed. Additionally, there is no cross-reference to a key fingerprint in the repository itself. Fix: Include the GPG key fingerprint directly in SECURITY.md so consumers can independently verify the key fetched from the URL. Consider also publishing the key to well-known public key servers (e.g., keys.openpgp.org) and document verification steps in detail.
  • Low · GitHub Actions Workflows Use Third-Party Actions Without SHA Pinning — .github/workflows/, .github/actions/. The repository contains multiple GitHub Actions workflow files under .github/workflows/ and .github/actions/. From the file listing, it is not possible to confirm whether third-party actions (e.g., actions/checkout, actions/setup-java, etc.) are pinned to specific commit SHAs. Using mutable version tags (e.g., @v3) instead of immutable commit SHAs for third-party actions is a known CI/CD supply-chain risk — a compromised or updated action could execute malicious code in the build pipeline. Fix: Pin all third-party GitHub Actions to their full commit SHA (e.g., actions/checkout@<full-sha>) rather than mutable tags. Use a tool like Dependabot or StepSecurity's Harden-Runner to automatically manage and audit action pins. Periodically review and update pinned SHAs.
  • undefined · undefined — undefined. undefined Fix: undefined

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

GO · spring-projects/spring-framework — RepoPilot Verdict