Answer
At constructor time only constructor-injected dependencies are available; field- and setter-injected collaborators are still null, and any proxying the container will apply hasn't happened yet. @PostConstruct runs after the bean is fully wired, so cache warming, validation, or registration that depends on collaborators is safe there. Doing such work in the constructor risks NullPointerExceptions, calling through a not-yet-proxied reference (so @Transactional/@Async won't apply), and makes construction slow and side-effectful, which hurts testability.
Common mistakes
- Doing I/O in a constructor before dependencies are injected.
- Assuming @PostConstruct runs inside a transaction.