Spring создает экземпляры bean-компонентов и внедряет для них зависимости в соответствии с их отношением.
Spring гарантирует, что объявленному bean-компоненту будут введены / установлены все его зависимости до того, как он вызовет свой аннотированный метод @PostConstruct
.
Вот отношения между бобами:
Test --uses -> Test2
Test2 --uses -> Test
Вот как это работает:
1) Spring создает экземпляр компонента, а затем другого, не вводя их зависимости. Пока порядок не имеет значения.
2) Spring вводит зависимости для первого компонента. Так как здесь зависимости являются двунаправленными, Spring произвольно решает, какой компонент должен обрабатывать первый. В вашем случае, согласно вашей ошибке, Spring сначала обрабатывает Test2
.
3) Spring вызывает метод @PostConstruct
компонента Test2
после установки его зависимостей.
Метод, который вы определили, вызывает метод бин Test
, использующий поле зависимости (Test2 test2
). Но поскольку зависимости этого bean-компонента еще не установлены, это поле имеет значение null, и доступ к нему вызывает NPE.
В вашем рабочем случае вы вызываете из Test2
метод Test
, который не ссылается на его поля зависимостей.
Обратите внимание, что циклические c зависимости обычно не рекомендуются. Вот иллюстрация проблем, которые могут возникнуть.
Когда вы не можете удалить их, вы должны, по крайней мере, избегать вызова другого компонента в методе @PostConstruct
, потому что он наносит ущерб работе, выполняемой контейнером, чтобы прервать цикл во время их инициализация.