这是关于我们考虑添加到Web Beans中的注入点元数据API的另一个用例。我一直认为能够按角色注入实体实例,而不是在系统中传递引用,会很好。(在Seam中,你可以使用home对象来达到这个目的。)
当然,我们需要一种方法来区分我们感兴趣的特定实体类型的哪个实例。对于每次对话,都有某些“角色”。例如,在用户管理屏幕中,有当前用户和正在管理的用户。
在Web Beans的世界里,我们会使用注解来表示一个角色。例如,我们会引用@Administered User。我希望能够做的是在对话开始时将标识符与角色关联起来,然后只需将该标识符注入到任何在这次对话中调用的Web Bean中。当然,我可以写一个带有生产方法的Web Bean来做这件事
@ConversationScoped public class AdministeredUser { private @PersistenceContext EntityManager em; private String userId; public void setUserId(String userId) { this.userId = userId; } @Produces @Administered User getUser() { return userId==null ? null : em.find(userId); } }
然而,我真的不想为每个角色都写一个新的Web Bean!所以让我们通用这个代码。而不是使@Administered成为一个绑定注解,我们将使用一个泛型绑定类型@Persistent,并使用InjectionPoint来确定注入点指定的角色
@ConversationScoped public class EntityRoles { private @PersistenceContext EntityManager em; private Map<Key, Object> idByRole = new HashMap<Key, Object>(); public void setId(Class entity, Annotation role, Object Id) { idByRole.put(new Key(entity, role), id); } @Produces @Persistent Object getInstance(InjectionPoint ij) { Object id = idByRole.get(new Key(ij.getType(), ij.getAnnotations())); return id==null ? null : em.find(id); } }
(我省略了无聊的Key的实现,以及绑定注解@Persistent.)
现在,以下代码可以在对话开始时设置标识符
@Current EntityRoles er; ... er.setId(User.class, Administered.class, userId);
并且User可以这样注入
@Administered @Persistent User user
我们可能还希望使引用User在Unified EL中通过名称引用,但为此我们需要编写一个ELResolver(这在这个帖子中也太无聊了)。