Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
public class SpringConfig implements BeanFactoryPostProcessor {
@Bean
public UserScope userScope(ConfigurableListableBeanFactory beanFactory) {
return new UserScope(beanFactory);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
final UserScope userScope = beanFactory.getBean(UserScope.class);
beanFactory.registerScope(UserScope.SCOPE, userScope);
}
}
public class UserScope implements Scope {
public static final String SCOPE = "user";
private static final Logger logger = LoggerFactory.getLogger(UserScope.class);
private static final ThreadLocal<User> USER = new ThreadLocal<>();
private final Object lock = new Object();
private final ConfigurableListableBeanFactory beanFactory;
private final Cache<String, Map<String, Object>> conversations;
public UserScope(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
// По истечению 1 часа пользовательские бины удаляются
conversations = CacheBuilder.newBuilder()
.expireAfterAccess(1, TimeUnit.HOURS)
.removalListener(notification -> {
if (notification.wasEvicted()) {
Map<String, Object> userScope = (Map<String, Object>) notification.getValue();
userScope.values().forEach(this::removeBean);
}
})
.build();
}
public static User getUser() {
return USER.get();
}
public static void setUser(User user) {
USER.set(user);
}
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
final String userId = getConversationId();
if (userId != null) {
final String userName = MessageUtils.getSenderName(getUser());
Map<String, Object> beans = conversations.getIfPresent(userId);
if (beans == null) {
synchronized (lock) {
beans = conversations.getIfPresent(userId);
if (beans == null) {
beans = new ConcurrentHashMap<>();
conversations.put(userId, beans);
logger.debug("Bean storage for user '{}' is initialized", userName);
}
}
}
Object bean = beans.get(name);
if (bean == null) {
bean = objectFactory.getObject();
beans.put(name, bean);
logger.debug("Bean {} is created for user '{}'", bean, userName);
}
return bean;
}
//return null;
throw new RuntimeException("There is no current user");
}
@Override
public Object remove(String name) {
final String userId = getConversationId();
if (userId != null) {
final Map<String, Object> userBeans = conversations.getIfPresent(userId);
if (userBeans != null) {
return userBeans.remove(name);
}
}
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
final User user = getUser();
return user == null ? null : user.getId().toString();
}
public void removeConversation() {
final String userId = getConversationId();
if (userId != null) {
final String userName = MessageUtils.getSenderName(getUser());
final Map<String, Object> beans = conversations.getIfPresent(userId);
if (beans != null && !beans.isEmpty()) {
beans.values().forEach(this::removeBean);
synchronized (lock) {
conversations.invalidate(userId);
logger.debug("Bean storage for user '{}' is invalidated", userName);
}
}
}
}
private void removeBean(Object bean) {
try {
beanFactory.destroyBean(bean);
} catch (Exception ex) {
logger.error("An error has occurred during destroying bean {}", bean, ex);
}
}
}
Я не пишу на Java, но TelegramUpdateHandlerBeanPostProcessor это шутка такая?
Это набирать вообще реально? Или в Java это так и надо делать...
Я: Оповещения
Бот: О чем нужно оповещать?
Я: Курс валют
Бот: Утром, Днем, Ночью, Каждый час?
Я: Утром
Бот: В какое время? (9:00, 10:00, 11:00, 12:00)
Я: 9:00
Бот: Отлично, каждое утро в 9:00 я буду предоставлять тебе свежую информацию по курсам валют.
Плюс я правильно понимаю, что программист будет вынужден реализовывать функционал для каждого шага?Нет, необязательно. Достаточно реализовать прием команд и отправление ответов и переиспользовать этот функционал на каждом следующем шаге.

Этот XML можно легко заменить одним Java-классом, с enum-ом всех возможных состояний и методами для каждого состояния.
Разработка telegram бота с использованием Spring