Мне пришлось создать singleton bean-компонент вручную в классе @Configuration, чтобы поделиться им, не раскрывая его в контексте (который запускает условные выражения/автоконфигурации). Мне было указано на осознание определенных рисков, чтобы справиться с этим самостоятельно:
Код следующий:
private DataSource nonExposedDatasource;
public DataSource nonExposedSingletonDataSource() {
if (Objects.isNull(this.nonExposedDatasource)) {
this.nonExposedDatasource = this.myPrivateDatasourceProperties.initializeDataSourceBuilder().build();
}
return this.nonExposedDatasource;
}
@Bean
public TaskConfigurer taskConfigurer() {
return new DefaultTaskConfigurer(this.nonExposedSingletonDataSource());
}
@Bean
public BatchConfigurer batchConfigurer() {
return new DefaultBatchConfigurer(this.nonExposedSingletonDataSource());
}
У меня вопрос: действительно ли у меня есть риск не заметить это? Разве Спринг недостаточно умен?
Что касается безопасности потоков, я понимаю, что мой код должен быть проблематично, должно произойти 2 потока, обрабатывающих @Конфигурация. Spring так делает??
Что касается утечки ресурсов, если бы мой источник данных был @Bean, управляемым Spring, как работает большинство приложений, не было бы это потенциальной ловушкой, если приложение все равно закроется?
Как бы вы сделали этот код безопаснее?
Это относится к одному из комментариев здесь: stackoverflow.com/questions/55248571/… «При выполнении подобных действий убедитесь, что вы также регистрируете обратный вызов для закрытия соединений, когда приложение остановлено. В противном случае вы можете оставить открытые (tcp) соединения, обычно это будет обрабатываться из-за к тому, что это фасоль». (но это не @Bean)
Я даже не знаю, как можно было бы закрывать соединения, открытые из источника данных, если бы вы не открывали его в первую очередь: интерфейс не дает возможности сделать это. Хотя, учитывая, что в связанном вопросе вы говорите, что это источник HikariCP, вы можете зарегистрировать отключение, если хотите. Что касается безопасности данных, я ожидаю, что HikariDS будет потокобезопасным, но что не является потокобезопасным, так это доступ к его экземплярам. Вам нужно как-то синхронизировать это самостоятельно.
Итак, если я правильно понимаю, мне не следует беспокоиться об утечке соединения, но я должен беспокоиться о синхронизации, значит ли это, что Spring может загружать @Configuration через разные потоки?
Здесь следует отметить, что единственным использованием моего объекта источника данных является Spring Framework через DefaultTaskConfigurer и DefaultBatchConfigurer (как показано в коде), поэтому я предполагаю, что вопрос заключается в том, требует ли факт отсутствия управления как @Bean какой-либо специальной обработки для синхронизации
если я правильно понимаю, вы можете объявить свои bean-компоненты как lazy-init, и в этот момент Spring не будет заботиться о создании ваших bean-компонентов, если от них что-то не зависит. Эта зависимость может быть реализована вашим кодом, вызывающим BeanFactory для получения экземпляра из разных потоков. В вашей настройке, я думаю, конфигурация будет однопоточной.
Поскольку это уже довольно длинная дискуссия, могу ли я спросить, почему вы делаете все это в первую очередь (т.е. почему ваш источник данных не является @Bean)? Если вы не хотите, чтобы bean-компонент выставлялся наружу, тогда Spring тебя уже прикрыли, не нужно проходить через всю эту чепуху. Также обратите внимание, что если ваш bean-компонент вообще является Closeable, то Spring также вас прикрыл.
Я уже видел эту документацию, но она должна быть старой или что-то в этом роде, так как у меня она не работала. stackoverflow.com/questions/55063611/…
Похоже, это другая часть функциональности, которая не работала. Вы хотели не экспортировать bean-компонент, но... все равно экспортируй, значит, он доступен автоконфигураторам? Не так уж много смысла, но хорошо. Что такое конфигуратор - постпроцессор bean? Какая у вас реализация постпроцессора не работает?
Как раз наоборот. Я хотел, чтобы Spring управлял компонентом, но не из @Configuration, чтобы мои автоконфигураторы не запускались.




DataSourceэто не закрываемый, поэтому я не уверен, что вы имеете в виду под «незакрытым явно». В документахDataSourceтакже не обсуждаются гарантии потокобезопасности конкретного источника или его соединений — вам придется уточнить у разработчика драйвера, какие гарантии предоставляются. Кроме того, учтите, что транзакции Spring всегда привязаны к потоку (атрибуты — этоThreadLocal), поэтому я полностью ожидаю, что он также будет связывать потоки с объектамиConnection.