All Java templates

Spring Framework Core Rules

Dependency injection, bean lifecycle, configuration classes, and profiles.

DevZone Tools2,580 copiesUpdated Apr 16, 2026SpringJava
# CLAUDE.md — Spring Framework Core

## Dependency injection

- **Constructor injection** for required dependencies. Final fields, no `@Autowired` needed when there's a single constructor.
- Field injection (`@Autowired` on a field) is banned. It hides dependencies and breaks immutability.
- Setter injection only for legitimately optional collaborators.
- One bean = one responsibility. Wide constructors are a sign of a bean doing too much.

## Bean configuration

- Java config (`@Configuration` + `@Bean`) over XML. XML is only for legacy.
- Use `@Component` / `@Service` / `@Repository` on classes you own. `@Bean` methods for third-party types and conditional wiring.
- Avoid mixing `@ComponentScan` with manual `@Bean` registration of the same type — the precedence rules surprise you.

## Configuration properties

- `@ConfigurationProperties` over `@Value`. Strongly typed, auto-completed, validated.
- Use records for property classes:
  ```java
  @ConfigurationProperties("app.email")
  record EmailProperties(String fromAddress, String smtpHost, int smtpPort) {}
  ```
- Validate with Bean Validation: `@Validated` on the class, `@NotNull`, `@NotEmpty` on fields.

## Profiles

- One profile per environment: `dev`, `test`, `prod`. Configure with `spring.profiles.active`.
- Don't put production-specific behavior behind a `if` on a profile name. Use `@Profile` on beans.
- `@Profile("!prod")` for "everywhere except prod" beans (dev tools, mock integrations).

## Lifecycle

- `@PostConstruct` for initialization that requires dependency injection to be complete.
- `@PreDestroy` for cleanup. Triggered on graceful shutdown.
- Don't do work in constructors that touches the network, database, or threads. The bean isn't fully wired yet.

## Events

- `ApplicationEventPublisher` for in-process events. Decouples producers from consumers.
- Listeners are `@EventListener` methods. Avoid `ApplicationListener<EventType>` — older API.
- For async listeners, use `@Async` + `@EnableAsync`. Configure the executor explicitly — the default isn't safe for production.

## Transactions

- `@Transactional` on service methods. Don't put it on controllers or repositories.
- Default propagation `REQUIRED` is right 95% of the time.
- `readOnly = true` for queries — Hibernate optimizes flush behavior.
- Self-invocation doesn't trigger the proxy: a `@Transactional` method calling another `@Transactional` method on `this` won't open a new transaction. Inject `self` or split the bean.

## Don't

- Don't inject the `ApplicationContext` to look up beans dynamically. That's service locator anti-pattern.
- Don't `BeanFactory.getBean()` from app code. If you need conditional wiring, use `@Conditional` or factories.
- Don't put initialization in static blocks. Use `@PostConstruct` or `CommandLineRunner`.
- Don't catch and swallow `RuntimeException` to "make Spring happy" — the framework's exception handling is intentional.

Other Java templates