当前页面: 开发资料首页 → JSP 专题 → EJB 3.0+Aspect实现声明性编程初步
摘要: EJB 3.0+Aspect实现声明性编程初步
@Stateful
public class CartBean implements ShoppingCart
{
private float total;
private Vector productCodes;
public int someShoppingMethod(){...};
...
}
public class TravelAgencyServiceImpl implements ITravelAgencyService
{
public IFlightDAO flightDAO;
public TravelAgencyServiceImpl()
{ flightDAO = FlightDAOFactory.getInstance().getFlightDAO(); }
public void bookTrip(long outboundFlightID, long returnFlightID, int seats)
throws InsufficientSeatsException
{
reserveSeats(outboundFlightID, seats);
reserveSeats(returnFlightID, seats);
}
}
public class TravelAgencyServiceImpl implements ITravelAgencyService
{
@Resource(name = "flightDAO")
public IFlightDAO flightDAO;
public void bookTrip(long outboundFlightID, long returnFlightID, int seats)
throws InsufficientSeatsException
{
reserveSeats(outboundFlightID, seats);
reserveSeats(returnFlightID, seats);
}
}
@Aspect
public class InjectionAspect
{
private DependencyManager manager = new DependencyManager();
@Before("get(@Resource * *.*)")
public void beforeFieldAccesses(JoinPoint thisJoinPoint)
throws IllegalArgumentException, IllegalAccessException
{
FieldSignature signature = (FieldSignature) thisJoinPoint.getSignature();
Resource injectAnnotation = signature.getField().getAnnotation(Resource.class);
Object dependency = manager.resolveDependency(signature.getFieldType(),injectAnnotation.name());
signature.getField().set(thisJoinPoint.getThis(), dependency);
}
}
这个简单方面所做的全部是,从一个属性文件(这个逻辑被封装在DependencyManager对象中)查询实现类并且在存取字段之前把它注入到用@Resource注解所注解的字段中。显然,这种实现不是完整的,但是它确实说明了你可以怎样以一种JSR 250兼容方式且不需采用EJB来提供资源注入。
四、 安全性
除了资源注入外,JSR 250和EJB 3.0还提供经由注解的元数据安全表示。javax.annotation.security包定义了五个注解-RunAs,RolesAllowed,PermitAll,DenyAll和RolesReferenced-所有这些都能应用到方法上来定义安全要求。例如,如果你想要声明上面列出的bookFlight方法仅能为具有"user"角色的调用者所执行,那么你可以用如下的安全约束来注解这个方法:
public class TravelAgencyServiceImpl implements ITravelAgencyService
{
@Resource(name = "flightDAO")
public IFlightDAO flightDAO;
@RolesAllowed("user")
public void bookTrip(long outboundFlightID, long returnFlightID, int seats)
throws InsufficientSeatsException
{
reserveSeats(outboundFlightID, seats);
reserveSeats(returnFlightID, seats);
}
}
@Aspect
public class SecurityAspect
{
@Around("execution(@javax.annotation.security.RolesAllowed * *.*(..))")
public Object aroundSecuredMethods(ProceedingJoinPoint thisJoinPoint)
throws Throwable
{
boolean callerAuthorized = false;
RolesAllowed rolesAllowed = rolesAllowedForJoinPoint(thisJoinPoint);
for (String role : rolesAllowed.value())
{
if (callerInRole(role))
{ callerAuthorized = true; }
}
if (callerAuthorized)
{ return thisJoinPoint.proceed(); }
else
{
throw new RuntimeException("Caller not authorized to perform specified function");
}
}
private RolesAllowed rolesAllowedForJoinPoint(ProceedingJoinPoint thisJoinPoint)
{
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
return targetMethod.getAnnotation(RolesAllowed.class);
}
private boolean callerInRole(String role)
{ ... }
}
五、 事务
事务成为企业开发的一个重要部分-因为它们有助于在一个并发的环境中的数据集成。从一个高层次上看,事务可以通过多种或者是完整的或者是都不完整的操作来保证这一点。
不象针对资源注入和安全的注解,针对事务的注解是特定于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(); }
}
@Stateful
public class TravelAgencyServiceImpl implements ITravelAgencyService
{ ... }