spring-projects/spring-framework
Patterns and conventions
The Spring Framework codebase has been written and maintained for nearly two decades. It carries strong, consistent conventions. New contributions must match the surrounding style.
File and package layout
- One public type per file. Inner static helper types are fine.
- Packages mirror module-level domains:
org.springframework.<module>.<area>. *.supportpackages contain implementation helpers;*.configpackages contain configuration classes;*.annotationpackages contain annotations and their processors.- Internal-only types (not for public consumption) live in packages whose name ends with
.support,.internal, or are package-private.
Class structure
Within a typical Spring class:
- License header (Apache 2.0)
- Package
- Imports (no wildcards; ordered:
java.*,jakarta.*, third-party,org.springframework.*) - Javadoc
- Class declaration
- Fields —
static finalfirst, thenfinal, then mutable - Constructors — primary first
- Public methods — grouped by concept, not alphabetical
- Protected/private helpers — at the bottom
- Inner classes — last
Nullness annotations
The codebase is in an active migration from Spring's own org.springframework.lang.@Nullable to JSpecify (org.jspecify.annotations.@Nullable).
- New code should prefer JSpecify annotations where the surrounding module has already been migrated.
- Each module's nullness rules are validated by the
io.spring.nullabilityGradle plugin at build time. - A
package-info.javatypically declares@NullMarkedor@NonNullApito set the default. - A method that returns
nullmust be annotated@Nullable. A parameter that acceptsnullmust be annotated@Nullable. The build will fail otherwise.
Generics, type tokens, and ResolvableType
When a method needs the full generic type (not just the raw class), the codebase uses org.springframework.core.ResolvableType rather than Type/ParameterizedType directly. ResolvableType resolves type variables across class hierarchies and is the standard for advanced generic work in this codebase.
ResolvableType resolved = ResolvableType.forMethodReturnType(method);
ResolvableType element = resolved.getGeneric(0);Logging
- Use Apache Commons Logging (
org.apache.commons.logging.Log) — Spring ships its own SLF4J-bridge, so this is effectively SLF4J under the hood. - Acquire loggers via
LogFactory.getLog(getClass())and store asprotected final Log logger = …. - Use
if (logger.isDebugEnabled())only for expensive message construction. - Log levels:
errorfor unexpected failures,warnfor recoverable problems,infofor major lifecycle events,debugfor routine internal flow,tracefor fine-grained details.
Exception conventions
- Public APIs throw runtime exceptions for programmer/configuration errors and checked exceptions only when they're intrinsic to the operation (rare; Spring largely avoids checked exceptions).
- Exception hierarchies are deep and well-organized. For example:
BeansException←BeanInitializationException,NoSuchBeanDefinitionException, …DataAccessException←DataAccessResourceFailureException,DataIntegrityViolationException, …
- New exception types extend the closest framework parent, not
RuntimeExceptiondirectly. - Translate underlying SQLException / JMSException / etc. into Spring's hierarchy at the API boundary using
*ExceptionTranslatorclasses.
Error message style
- Sentences end with periods. Multi-line error messages have one sentence per period.
- Include the offending value (
"Failed to resolve bean: " + beanName) — log lines without identifiers are unhelpful. - Use
Assert(org.springframework.util.Assert) for precondition checks:Assert.notNull(value, "Value must not be null").
Annotation design
- Stereotype annotations (
@Component,@Service, …) are meta-annotated for composability. @AliasForis used heavily to alias annotation attributes between annotations.- Annotation processors live in
*.annotationpackages and typically extendBeanFactoryPostProcessororBeanDefinitionRegistryPostProcessor.
Configuration class style
- Prefer
@Configurationwith@Beanmethods to XML for new code. @Configuration(proxyBeanMethods = false)is preferred for "lite" configurations that don't depend on inter-@Bean-method calls — produces less reflection and works better in native images.@Conditional-style annotations are used sparingly in the framework itself; they're more common in Spring Boot.
Code formatting
- Tabs for indentation, not spaces (intentional, consistent across decades).
- Line length: ~120 characters is the soft limit.
- Braces on same line (Java standard, K&R variant).
- Imports: no wildcards; ordering enforced by Checkstyle.
The full code style is documented at Spring's Code Style wiki page; IntelliJ settings live at IntelliJ IDEA Editor Settings.
Internationalization
- Public-facing string resources go through
MessageSource. - Internal exception messages and logs are English only.
Backwards compatibility
- The framework guarantees binary and source compatibility within a minor release line (e.g., 7.0.x).
- Major releases (e.g., 7.0 → 7.1, 6.x → 7.x) may break compatibility but must be documented in the upgrade guide.
- New methods added to public interfaces must be
defaultto preserve compatibility. - Deprecated APIs are kept for at least one minor cycle and removed in the next major. Use
@Deprecated(since = "X.Y", forRemoval = true).
Reactive code conventions
- Public reactive APIs return
Mono<T>orFlux<T>— never rawPublisher<T>(so users get the operator-rich Reactor types). - Methods that adapt to other reactive libraries go through
ReactiveAdapterRegistry(spring-core). - Avoid blocking inside reactive flows. The codebase uses
BlockHoundin some test runs to enforce this.
Kotlin conventions
- Kotlin extensions for framework APIs live alongside Java code in
<module>/src/main/kotlin/. - Extension files are named after the type they extend, e.g.,
BeanFactoryExtensions.kt. - Spring's Kotlin code uses idiomatic Kotlin (data classes, extension functions, DSL builders).
Test conventions
See testing — test class style mirrors production class style.
See also
- Development workflow — branch and PR mechanics
- Tooling — build plugins that enforce these conventions
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.