프로젝트의 실제 개발 프로세스에는 이러한 비즈니스 시나리오가 많이 있습니다. 트랜잭션에서 하나의 비즈니스 로직을 처리 한 후 다른 비즈니스 로직을 처리해야합니다. 의사 코드는 대략 다음과 같습니다.
@Service
public class ProductServiceImpl {
...
public void saveProduct(Product product) {
productMapper.saveOrder(product);
notifyService.notify(product);
}
...
}
매우 간단하고 일반적인 비즈니스 논리 : 먼저 제품을 데이터베이스에 저장 한 다음 알림을 보냅니다.
언젠가는 새 제품을 Es에 저장해야 할 수 있습니다. 이때 코드는 다음과 같이 될 수 있습니다.
@Service
public class ProductServiceImpl {
...
public void saveProduct(Product product) {
productMapper.saveProduct(product);
esService.saveProduct(product)
notifyService.notify(product);
}
...
}
비즈니스 요구 사항이 변경되면 코드를 계속해서 수정해야합니다. 그리고 또 다른 문제가 있는데 알림 시스템이 다운되면 더 이상 제품을 추가 할 수 없습니다.
위의 상황에서는 비즈니스를 분리하기 위해 메시지 미들웨어 (메시지 큐)를 도입하는 것이 매우 적합하지만 모든 비즈니스 시스템이 메시지 미들웨어를 도입하는 것은 아닙니다 (제 3 자 아키텍처 구성 요소의 도입으로 큰 운영 및 유지 관리 비용이 발생 함).
Spring은 이러한 요구를 달성하는 데 도움이되는 이벤트 중심 메커니즘을 제공합니다.
봄 이벤트 주도
스프링 이벤트 드라이브는 세 부분으로 구성됩니다.
ApplicationEvent : 이벤트 자체를 나타냅니다. 사용자 지정 이벤트는 이벤트를 정의하기 위해이 클래스를 상속해야합니다.
ApplicationEventPublisher : 주로 이벤트를 게시하는 데 사용되는 이벤트 전송기
ApplicationListener : 이벤트 리스너 인터페이스, 리스너 클래스는 ApplicationListener에서 onApplicationEvent 메소드를 구현하거나 메소드에 @EventListener를 추가하여 이벤트 모니터링을 실현할 수 있습니다.
일반적으로 Spring 이벤트 구동을 구현하는 단계는 세 단계뿐입니다.
게시해야하는 이벤트 클래스를 사용자 지정하려면 ApplicationEvent 클래스를 상속해야합니다.
ApplicationEventPublisher를 사용하여 사용자 지정 이벤트 게시
@EventListener를 사용하여 이벤트 수신
"여기에서 특별한주의가 필요합니다. 기본적으로 이벤트는 동기식입니다. 즉, 이벤트가 게시 된 후 리스너가 처리 할 때까지 기다립니다. 이벤트가 게시 된 비즈니스에 트랜잭션이있는 경우 리스너는 동일한 트랜잭션에서 처리됩니다. 비동기 처리가 필요한 경우 이벤트의 경우 onApplicationEvent 메서드에 @Aync를 추가하여 비동기를 지원하거나 @EventListener를 사용하여 주석이있는 메서드에 @Aync를 추가 할 수 있습니다. "
소스 코드 전투
이벤트 만들기
public class ProductEvent extends ApplicationEvent {
public ProductEvent(Product product) {
super(product);
}
}
이벤트 게시
@Service
public class ProductServiceImpl implements IproductService {
...
@Autowired
private ApplicationEventPublisher publisher;
@Override
@Transactional(rollbackFor = Exception.class)
public void saveProduct(Product product) {
productMapper.saveProduct(product);
//事件发布
publisher.publishEvent(product);
}
...
}
이벤트 모니터링
@Slf4j
@AllArgsConstructor
public class ProductListener {
private final NotifyService notifyServcie;
@Async
@Order
@EventListener(ProductEvent.class)
public void notify(ProductEvent event) {
Product product = (Product) event.getSource();
notifyServcie.notify(product, "product");
}
}
SpringBoot 시작 클래스에
@EnableAsync
주석 추가
@Slf4j
@EnableSwagger2
@SpringBootApplication
@EnableAsync
public class ApplicationBootstrap {
...
}
Async 사용 후 기본 스레드 풀 SimpleAsyncTaskExecutor가 사용되며 일반적으로 프로젝트에서 스레드 풀을 사용자 정의합니다.
@Configuration
public class ExecutorConfig {
/** 核心线程数 */
private int corePoolSize = 10;
/** 最大线程数 */
private int maxPoolSize = 50;
/** 队列大小 */
private int queueCapacity = 10;
/** 线程最大空闲时间 */
private int keepAliveSeconds = 150;
@Bean("customExecutor")
public Executor myExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("customExecutor-");
executor.setKeepAliveSeconds(keepAliveSeconds);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
이 기사가 도움이된다면
저에게 트리플을주는 것을 잊지 마세요 :
좋아요, 다시 게시, 댓글
。
다음에 만나요!
백인 매춘부 와 같은 좋아하는 , 엄지 손가락 은 진실입니다!
종료
건조물 공유
여기 모두에게 작은 선물이 있습니다. 공식 계정을 따르고 다음 코드를 입력하면 Baidu 네트워크 디스크 주소를 얻을 수 있으며 루틴이 없습니다!
001 : "프로그래머가 반드시 읽어야 할 책"
002 : "중소 인터넷 기업을위한 백엔드 서비스 아키텍처 및 운영 및 유지 보수 아키텍처 구축"
003 : "인터넷 기업을위한 높은 동시성 솔루션"
004 : "인터넷 Architecture Teaching Video "
006 : SpringBoot
주문 시스템 구현" 007 : "SpringSecurity 실제 전투 비디오"
008 : "Hadoop 실제 전투 교육 비디오"
009 : "Tencent 2019 Techo Developer Conference PPT"
010 : WeChat 교환 그룹
최근 인기 기사 상단
2. 아직 ETL을 이해 하지 못합니다.이 기사를 살펴보십시오.
나는 당신이 "보고"있다는 것을 알고