image.png
Spring框架通过其丰富的注解如@EnableAsync
和@Async
,为应用提供了强大的异步处理能力,允许开发者轻松地将方法调用异步化,有效提升应用的响应性和吞吐量。同时,事件发布和监听机制,以@EventLog
和@EventListener
注解为代表,使得应用组件之间的解耦和交互更加灵活。这些注解的结合使用,为构建复杂而高效的企业级应用提供了强有力的支持。
肖哥弹架构 跟大家“弹弹” 框架注解使用,需要代码关注
历史热点文章
- 28个验证注解,通过业务案例让你精通Java数据校验(收藏篇)
- Java 8函数式编程全攻略:43种函数式业务代码实战案例解析(收藏版)
- 69 个Spring mvc 全部注解:真实业务使用案例说明(必须收藏)
- 24 个Spring bean 全部注解:真实业务使用案例说明(必须收藏)
- MySQL索引完全手册:真实业务图文讲解17种索引运用技巧(必须收藏)
- 一个项目代码讲清楚DO/PO/BO/AO/E/DTO/DAO/ POJO/VO
1、异步执行
@EnableAsync
- 注解作用介绍
@EnableAsync
注解用于在配置类上开启对异步方法的支持。
- 注解属性介绍
无属性。
- 注解业务案例
@Configuration
@EnableAsync
public class AsyncConfig {
// 配置异步相关的Bean
}
@Async
- 注解作用介绍
@Async
注解用于声明一个方法为异步执行的方法。
-
注解属性介绍
-
value
或methodName
: 指定执行异步操作的线程池名称。
-
- 注解业务案例
@Service
public class AsyncService {
@Async("myAsyncExecutor")
public void performAsyncTask() {
// 异步执行的逻辑
}
}
2、事件发布与监听
@EnableEventLog
- 注解作用介绍
@EnableEventLog
注解用于开启事件的日志记录功能(如果有自定义实现)。
- 注解属性介绍
无属性。
- 注解业务案例
@Configuration
@EnableEventLog
public class EventLogConfig {
// 配置事件日志相关的Bean
}
@EventLog
- 注解作用介绍
@EventLog
注解用于声明一个方法在执行后发布一个事件。
-
注解属性介绍
-
value
: 指定事件的类型。
-
- 注解业务案例
public class EventService {
@EventLog("userCreatedEvent")
public void registerUser(User user) {
// 用户注册逻辑
}
}
@EventListener
- 注解作用介绍
@EventListener
注解用于声明一个方法为事件监听器。
-
注解属性介绍
-
value
: 指定监听的事件类型。 -
condition
: 指定条件表达式,用于决定是否处理事件。
-
- 注解业务案例
public class EventConsumer {
@EventListener(UserCreatedEvent.class)
public void onUserCreated(UserCreatedEvent event) {
// 处理用户创建事件
}
}
3、条件化配置
@Conditional
- 注解作用介绍
@Conditional
注解用于根据条件包含配置。
-
注解属性介绍
-
value
: 指定条件类。
-
- 注解业务案例
public class MyConditionalConfig {
@Bean
@Conditional("#{beanFactory.containsBean('someBean')}")
@Conditional(MyCustomCondition.class)
public SomeBean someBean() {
return new SomeBean();
}
}
4、异步注解综合案例
import org.springframework.aop.framework.autoproxy.AsyncAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
// 配置类,用于开启异步支持和自定义线程池
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
// 定义异步任务执行器
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2); // 设置核心线程数
executor.setMaxPoolSize(5); // 设置最大线程数
executor.setQueueCapacity(10); // 设置队列容量
executor.setThreadNamePrefix("Async-Thread-"); // 设置线程名前缀
executor.initialize();
return executor;
}
// 异常处理器,用于处理异步方法抛出的异常
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.out.println("Async method " + method.getName() + " threw an exception: " + ex.toString());
}
};
}
}
// 业务服务类,包含异步方法
@Service
public class AsyncService {
// 异步方法,无返回值
@Async
public void processOrder(Order order) {
try {
// 耗时的订单处理过程
Thread.sleep(3000);
System.out.println("Order processed in thread: " + Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 异步方法,有返回值,返回Future对象
@Async
public Future<String> fetchDataFromRemoteService() {
try {
//远程服务获取数据的过程
Thread.sleep(2000);
return new AsyncResult<>("Data fetched successfully");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return new AsyncResult<>(null);
}
}
}
// 订单实体类
class Order {
// 订单相关信息
}
// 应用程序主入口
public class AsyncApplication {
public static void main(String[] args) {
// 启动Spring应用上下文
}
}
-
AsyncConfig
类通过实现AsyncConfigurer
接口来配置异步任务执行器(线程池)和异步方法的异常处理器。 -
AsyncService
类中的processOrder
方法和fetchDataFromRemoteService
方法被标记为@Async
,表示它们将在异步执行器配置的线程池中异步执行。 -
processOrder
方法了处理订单的耗时操作,而fetchDataFromRemoteService
方法从远程服务获取数据的操作,并返回Future
对象。 - 异步方法抛出的异常将由
AsyncConfig
类中的异常处理器捕获并记录。
5、事件注解综合案例
1. 定义事件
首先定义一个应用事件UserRegisteredEvent
,它扩展了Spring的ApplicationEvent
类。
import org.springframework.context.ApplicationEvent;
public class UserRegisteredEvent extends ApplicationEvent {
private User user;
public UserRegisteredEvent(User user) {
super(user); // 将用户信息作为事件的来源
this.user = user;
}
public User getUser() {
return user;
}
}
2. 创建事件发布方法
在用户服务UserService
中,创建一个方法来发布UserRegisteredEvent
事件。
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final ApplicationContext applicationContext;
public UserService(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void registerUser(User user) {
// 注册用户逻辑
applicationContext.publishEvent(new UserRegisteredEvent(user));
}
}
3. 使用@EventListener
监听事件
然后,我们创建一个邮件发送服务EmailService
,它将监听UserRegisteredEvent
事件并发送邮件。
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class EmailService {
@EventListener
@Async // 异步发送邮件,提高性能
public void onUserRegistered(UserRegisteredEvent event) {
User user = event.getUser();
// 发送欢迎邮件逻辑
sendWelcomeEmail(user);
}
private void sendWelcomeEmail(User user) {
// 实际发送邮件的代码
}
}
4. (可选)使用@EventLog
记录事件
如果我们想要记录所有用户注册事件,可以创建一个自定义的@EventLog
注解,并在事件监听器中使用它。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventLog {
String value();
}
@Service
public class LoggingService {
@EventLog("userRegistered")
public void logUserRegistration(UserRegisteredEvent event) {
// 记录事件到日志系统的逻辑
logRegistration(event.getUser());
}
private void logRegistration(User user) {
// 实际记录日志的代码
}
}
请注意,@EventLog
是一个自定义注解,Spring框架本身并不提供此注解。在实际应用中,您可能需要实现自定义的日志记录逻辑。
5. 配置Spring以支持异步事件监听器
最后,确保Spring配置支持异步事件监听器,这可以通过在配置类上添加@EnableAsync
注解来实现。
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
// 异步配置
}