通用的Web Bean用于注入实体

发布者    |       CDI

这是关于我们考虑添加到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(这在这个帖子中也太无聊了)。


返回顶部