spring 无状态 bean

有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。 


无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
其中bean作用域中的singleton是无状态的作用域,prototype是有状态的作用域...bean的整个生命周期负责:容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。但对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype 
bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)
<think>好的,用户问的是“无状态 Bean”,我需要先确定他们对Java EE或Jakarta EE的了解程度。可能他们正在学习EJB或者在实际项目中使用到了无状态会话Bean,想了解其特性和用法。 首先,我应该解释什么是无状态Bean,强调它的生命周期和状态管理。用户可能想知道无状态Bean和有状态Bean的区别,所以需要对比说明。例如,无状态Bean不保存客户端状态,每次调用都是独立的,适合处理不需要会话状态的场景。 接下来,用户可能需要具体的代码示例,展示如何定义一个无状态Bean。应该包括注解的使用,比如@Stateless,以及如何注入依赖,比如使用@Inject或@EJB。同时,可能需要说明无状态Bean的线程安全问题,因为容器会管理实例池,但Bean本身不能有实例变量保存状态。 然后,应用场景和最佳实践也是重要的部分。用户可能想知道何时选择无状态Bean而不是其他类型的Bean,比如有状态或单例Bean。需要举例常见的应用场景,如服务层逻辑、工具类方法等。 另外,用户可能对无状态Bean的事务管理和安全性感兴趣。需要提到默认的事务管理方式,以及如何通过注解配置事务行为。同时,安全性的角色检查也是需要注意的点。 还要考虑用户可能的疑问,比如无状态Bean的性能优势,因为实例池的管理可以提高并发能力。但也要提醒不要滥用,比如避免在Bean中保存非线程安全的状态,或者过度依赖静态变量导致的问题。 最后,相关问题部分需要涵盖常见问题,如注入问题、事务配置、与Spring的对比等。确保问题能够引导用户深入理解无状态Bean的使用和注意事项。 需要检查是否有遗漏的关键点,比如生命周期回调方法(@PostConstruct, @PreDestroy),或者如何测试无状态Bean。同时,确保示例代码正确,符合规范,避免使用不推荐的做法。 总结来说,回答需要结构清晰,涵盖定义、特点、使用方法、最佳实践、应用场景以及常见问题,帮助用户全面理解无状态Bean的概念和使用方式。</think>无状态会话 Bean(Stateless Session Bean)是 Java EE/Jakarta EE 中 EJB 的核心组件之一,用于实现**无会话状态的服务层逻辑**。其核心特性是**不保存客户端的会话状态**,每次方法调用都是独立的,适合高并发场景下的业务处理。以下是详细解析: --- ### 1. **基本定义与注解** #### (1) **定义无状态 Bean** 通过 `@Stateless` 注解声明一个无状态会话 Bean: ```java @Stateless public class OrderService { @Inject private OrderRepository orderRepository; // 注入依赖 public void placeOrder(Order order) { orderRepository.save(order); } } ``` #### (2) **关键特性** | 特性 | 说明 | |---------------------|-------------------------------------------| | **无状态** | 不保存客户端的会话数据(如用户登录信息) | | **线程安全** | 容器管理实例池,单个实例可能被多线程复用 | | **依赖注入支持** | 可通过 `@Inject`、`@EJB` 注入其他组件 | | **事务管理** | 默认支持容器管理的事务(CMT) | --- ### 2. **生命周期与线程安全** #### (1) **生命周期管理** - **创建**:容器根据负载动态创建实例池。 - **销毁**:容器根据策略回收闲置实例。 - **回调方法**: ```java @PostConstruct public void init() { // 初始化逻辑(如加载缓存) } @PreDestroy public void cleanup() { // 资源释放(如关闭数据库连接) } ``` #### (2) **线程安全设计** - **禁止保存客户端状态**:避免使用实例变量存储用户数据(如 `private String userId;`)。 - **推荐做法**:将状态存储在方法局部变量或持久化存储中(如数据库)。 --- ### 3. **依赖注入与协作** #### (1) **注入其他组件** - 注入另一个无状态 Bean: ```java @EJB private PaymentService paymentService; ``` - 注入 CDI Bean(需启用 CDI): ```java @Inject private Logger logger; ``` #### (2) **解决循环依赖** 若出现 `A → B → A` 的循环依赖,可通过 `@EJB(lookup = "java:global/...")` 使用 JNDI 延迟绑定: ```java @EJB(lookup = "java:global/app/OrderService") private OrderService orderService; ``` --- ### 4. **事务管理** #### (1) **默认事务行为** - 所有公共方法默认在事务中执行(`REQUIRED` 传播模式)。 - 可通过 `@TransactionAttribute` 显式配置: ```java @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void processPayment(Payment payment) { // 新事务独立执行 } ``` #### (2) **事务传播模式** | 模式 | 行为说明 | |-----------------------|---------------------------------------| | `REQUIRED` | 如果存在事务则加入,否则新建事务 | | `REQUIRES_NEW` | 总是新建事务,挂起现有事务 | | `NOT_SUPPORTED` | 以非事务方式执行,挂起现有事务 | | `MANDATORY` | 必须存在事务,否则抛出异常 | --- ### 5. **安全性与角色检查** 通过 `@RolesAllowed` 限制方法访问权限: ```java @RolesAllowed("ADMIN") public void deleteOrder(Long orderId) { orderRepository.deleteById(orderId); } ``` #### (1) **获取当前用户** ```java @Resource private SessionContext sessionContext; public void checkUser() { Principal caller = sessionContext.getCallerPrincipal(); boolean isAdmin = sessionContext.isCallerInRole("ADMIN"); } ``` --- ### 6. **性能优化与最佳实践** #### (1) **避免滥用无状态 Bean** - **适用场景**:业务逻辑无状态(如支付处理、日志记录)。 - **不适用场景**:需要保存用户会话状态(应使用有状态 Bean 或 HTTP Session)。 #### (2) **减少远程调用开销** 若 Bean 需远程调用(如通过 RMI),应: - 合并细粒度方法为粗粒度接口。 - 使用 `@Remote` 接口明确暴露远程方法。 #### (3) **缓存与异步处理** - 结合 `@Singleton` Bean 实现缓存: ```java @Singleton public class CacheService { private Map<String, Object> cache = new HashMap<>(); // ... } ``` - 使用 `@Asynchronous` 异步执行: ```java @Asynchronous public Future<String> asyncTask() { // 长时间任务 return new AsyncResult<>("Done"); } ``` --- ### 7. **完整示例** #### (1) **订单服务 Bean** ```java @Stateless public class OrderService { @EJB private InventoryService inventoryService; @Inject private OrderRepository orderRepository; @TransactionAttribute(TransactionAttributeType.REQUIRED) public Order createOrder(OrderDTO dto) { Order order = convert(dto); inventoryService.checkStock(dto.getProductId()); return orderRepository.save(order); } @RolesAllowed("ADMIN") public void cancelOrder(Long orderId) { Order order = orderRepository.findById(orderId); order.setStatus("CANCELLED"); orderRepository.update(order); } } ``` #### (2) **客户端调用** ```java @EJB private OrderService orderService; public void placeOrder() { OrderDTO dto = new OrderDTO("product123", 2); Order order = orderService.createOrder(dto); System.out.println("Order created: " + order.getId()); } ``` --- ### 8. **与 Spring 的对比** | 特性 | EJB 无状态 Bean | Spring @Service Bean | |---------------------|-------------------------------|-------------------------------| | **事务管理** | 容器管理(CMT) | 基于 AOP 的声明式事务 | | **依赖注入** | 支持 `@Inject`、`@EJB` | 支持 `@Autowired`、`@Resource` | | **远程调用** | 原生支持 RMI-IIOP | 需整合 Spring Remoting | | **测试难度** | 依赖容器环境 | 可独立单元测试 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值