У меня есть приложение, в котором есть функция, которая включается или отключается с помощью параметра в application.properties, например
app.thingEnabled=true
И, конечно, это может быть правдой или ложью. И у меня в контроллере:
@Value("${app.thingEnabled:true}")
private boolean thingEnabled;
Конечно, мы проверяем, правда это или ложь, а затем либо делаем, либо не делаем.
Теперь я хочу, чтобы у этого был механизм обратной связи ... Например, функция Thing Feature записывает в базу данных. Если код БД обнаруживает исключение тайм-аута, установите для thingEnabled значение false на 5 минут, а затем повторите попытку. Что-то в этом роде.
Возможно ли это весной? Я подумал о создании отдельного компонента как, скажем, «ThingConfiguration», который мог бы иметь свойства, установленные на нем, а затем связать это свойство с ним, и контроллер просто вызвал бы его. Тогда у него может быть геттер и сеттер, которые могут обновляться динамически, но, похоже, может быть лучший способ.
Я также не совсем уверен, в какой момент создаются экземпляры этих классов и являются ли они общими для нескольких потоков обслуживания запросов.
Во-вторых, есть ли способ запустить поток, который спит эти 5 минут, а затем выполняет некоторую работу, не копаясь в api потоковой передачи низкого уровня? Я вижу, что есть @Scheduled, но похоже, что он предназначен для выполнения некоторой работы снова и снова, а не как что-то, инициированное самим кодом.
Он контролирует, следует ли код по тому или иному пути.
Что мешает сделать для него сеттер (я думаю, он у вас уже есть)? затем изменить его значение вперед и назад в зависимости от тайм-аута БД или чего-то еще?
Тогда возникает вопрос, как получить доступ к этому компоненту из другого места в коде, и если вам нравится @Autowired, ThingController - это один и тот же экземпляр для всех потоков выполнения? Или это изменит только свойство одного в том же потоке?
Пока я знаю ... простой @Autowired указывает на один экземпляр singleton для всех потоков. Одноэлементный режим по умолчанию для Spring beans.




Одна из вещей, которые вы, вероятно, захотите отделить, - это право на участие ваших запросов, выполняемых из их активация. thingEnabled определяет, активирован ли ваш процесс. Что-то еще должно определять, нужно ли запускать имеющий право.
В конечном итоге это зависит от того, как вы пишете свои запросы, но в Spring нет ничего, что могло бы спать в течение X минут, а затем обновлять ваш запрос. Однако, если вы разделите логику для определения права на участие, то написать что-нибудь, чтобы проверить, соответствуют ли временные отклонения вашему критерию, станет несколько проще. (Я оставляю это в качестве упражнения для читателя).
Чтобы ответить на заголовок:
Setting value of properties programatically in SpringBoot
Spring будет искать аннотации @Value только при запуске приложения, он не будет обновляться сам по себе после первого экземпляра. Например:
@Value("${app.thingEnabled:true}")
private boolean thingEnabled;
Это установит для thingEnabled значение, которое вы установили в application.properties, или true, если это свойство не найдено.
После этого, если вы установите для thingEnabled значение false, оно останется ложным. По сути, Spring будет назначать значение thingEnabled только при запуске, и никаких изменений вноситься не будет, если вы не сделаете их самостоятельно.
В твоем случае,
Now, I want to make this have a feedback mechanism... Like, the Thing Feature writes to a database. If the DB code catches a timeout exception, set thingEnabled to false for 5 mins and then try again.
Примерно так:
// database operation...
} catch (SQLTimeoutException e) {
thingEnabled = false;
// start a timerTask that will run in 5 minute, and then execute your code again
}
Но thingEnabled в данном случае не актуален, и я не понимаю, что вы здесь имеете в виду под feedback.
Я предполагаю, что вместо этого вы имели в виду запасной вариант.
В этом случае вы должны сделать следующее:
// database operation...
} catch (SQLTimeoutException e) {
if (thingEnabled) { // if the fallback is enabled
// start a timerTask that will run in 5 minute, and then execute your code again
}
}
Таким образом, установка app.thingEnabled действительно будет актуальна:
app.thingEnabled - это true, повторите попытку через 5 минут после исключения из тайм-аутаapp.thingEnabled - это false, не пытайтесь повторить попытку.Вы можете прочитать о Таймер и TimerTask. Также хороший пример можно найти здесь.
TimerTask не очень хорошо работает со Spring ... Каждую задачу необходимо создавать индивидуально, поэтому вы не можете автоматически подключать компоненты, управляемые Spring, в TimerTask.
@MichaelB Пока объект TimerTask находится внутри компонента, к нему можно получить доступ через автоматическое подключение самого компонента и доступ к TimerTask через него. В конечном итоге вы можете использовать ScheduledExecutorService, но Spring все еще не управляет этим.
Пример: ConfigReset cr - это автоматическое расширение TimerTask. Потом Timer timer = new Timer(); timer.schedule(cr, Date.from(Instant.now().plusSeconds(10)));. Он работает один раз, а затем вы получаете java.lang.IllegalStateException: Task already scheduled or cancelled, потому что вам нужен новый экземпляр класса TimerTask
Какова ваша конечная цель? Управляет ли это логическое значение чем-то, что можно легко внедрить, или бизнес-логикой? То есть, это контролирует, используете ли вы конкретный инъекционный компонент, или это контролирует, если вы идете по одному логическому пути над другим?