五、 事务
事务成为企业开发的一个重要部分-因为它们有助于在一个并发的环境中的数据集成。从一个高层次上看,事务可以通过多种或者是完整的或者是都不完整的操作来保证这一点。
不象针对资源注入和安全的注解,针对事务的注解是特定于EJB 3.0的并且没有在JSR 250普通注解中定义。EJB 3.0定义了两个与事务相联系的注解:TransactionManagement和TransactionAttribute。该TransactionManager注解指定事务是由容器所管理还是为bean所管理的。在EJB 3中,如果这个注解没被指定,那么将使用容器所管理的事务。TransactionAttribute注解用于指定方法的事务传播级别。有效值-包括强制的、要求的、要求新的、支持的、不支持的和从不支持的-用来定义是否要求一个已有事务或启动一个新的事务,等等。
因为bookFlight操作包含两步-订购一个外出航班和一个返回航班,所以,通过把它包装成一个事务,你能保证这项操作的一致性。通过使用EJB 3.0事务注解,这将看上去如下所示:
public class TravelAgencyServiceImpl implements ITravelAgencyService
{
@Resource(name = "flightDAO")
public IFlightDAO flightDAO;
@RolesAllowed("user")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void bookTrip(long outboundFlightID, long returnFlightID, int seats)
throws InsufficientSeatsException
{
reserveSeats(outboundFlightID, seats);
reserveSeats(returnFlightID, seats);
}
}
并且你可以应用一个简单的方面来自动地界定事务边界:
@Aspect
public class TransactionAspect
{
@Pointcut("execution(@javax.ejb.TransactionAttribute * *.*(..))")
public void transactionalMethods(){}
@Before("transactionalMethods()")
public void beforeTransactionalMethods()
{ HibernateUtil.beginTransaction(); }
@AfterReturning("transactionalMethods()")
public void afterReturningTransactionalMethods()
{ HibernateUtil.commitTransaction(); }
@AfterThrowing("transactionalMethods()")
public void afterThrowingTransactionalMethods()
{ HibernateUtil.rollbackTransaction(); }
}
这个实现基于这样的假设-Hibernate和无所不在的线程本地模式被用于管理Hibernate会话和事务对象;但是,任何其它适当的实现,例如基于JTA的实现,都能被代替使用。
六、 小结
通过使用EJB 3.0和JSR 250注解集,本文已经展示了例如资源管理、安全和事务等横切关注点是怎样被实现为方面的。当然,还有许多内容我们需进一步学习。首先要学的就是通过使用AspectJ的实现这些示例方面为模块化横切关注点所提供的蓝图。其次,我们已经看到了在如今正浮出水面的EJB 3.0声明背后的一些新思想和新概念。最后,我们还以戏剧性的方式看到了从EJB API中解耦我们的商业对象所必须要提供的自由。在这一点上,所有你想使TravelAgencyServiceImpl成为一个无状态会话要做的仅是添加一条最后的注解:
@Stateful
public class TravelAgencyServiceImpl implements ITravelAgencyService
{ ... }
最后,我非常希望这种自由地提供企业服务的方式会带来框架/容器工业界的竞争和革新。
