当前位置: 首页 > 知识库问答 >
问题:

@Application ationScoped CDI bean和@PeristextContext-这安全吗?

桂志新
2023-03-14

用CDI做这样的事情安全吗?

@Named
@ApplicationScoped
public class DAO {

   @PersistenceContext
   private EntityManager entityManager;

}

我理解EntityManager本身不是线程安全的,因此不应该在像@ApplicationScoped这样的共享全局上下文中使用。但是,由于带有@PersistenceContext的注入对象实际上是底层EntityManager周围的线程感知包装器,这是否可以?

我看过其他关于这个问题的帖子,但还没有找到这个具体案例的权威答案。例如:

Java CDI@PersistenceContext和线程安全

例如,与@Stateless一起使用似乎是安全的,但我不确定这是因为@Stateless的工作方式,还是因为@PersistenceContext本身固有的原因。

编辑我困惑的根源是注入的EntityManager包装器似乎知道当前线程,以便确定是否已经有正在进行的事务。所以也许我混淆了线程意识和线程安全,它们是两码事。

共有2个答案

钱稳
2023-03-14

这种方法怎么样:


    @RequestScoped
    class EntityManagerProducer {
    
        @PersistenceContext
        private EntityManager entityManager;
    
        @Produces
        @RequestScoped
        public EntityManager produceEntityManager() {
          return this.entityManager;
        }
    }

在任何范围的CDI bean中:


@Inject
private EntityManager entityManager;

应该在每个请求中创建实体管理器,当它传递一个它注入的CDI bean时创建一个新的实体管理器。在注入的CDI Bean中,您将获得一个在请求中使用的实体管理器。如果需要一个事务,实体管理器将加入它。因此,您在每个请求中都有一个新的实体管理器,这意味着,所有内容都在最后被清理干净,您不会有线程冲突。简单又容易,不是吗?

越飞翮
2023-03-14

我非常确定,在这种情况下,CDI不会为实体管理器创建上下文代理。毕竟,它的范围是什么?您可能需要类似于假设的@ThreadScoped或只是@RequestScoped,但@PersistenceContext不是CDI注释,CDI不会修改其语义。

所以这里发生的是JavaEE6平台的“托管bean”注入,这类似于在Servlet中注入实体管理器。这两种情况都提供了一个不能直接使用线程安全的实例。

例如,它看起来与@Stateless一起使用是安全的,但我不确定这是因为@Stateless的工作方式,还是因为@PersistenceContext本身固有的东西。

这是因为无状态的工作方式。对无状态bean上的方法的每个请求(调用)都由容器路由到唯一实例。容器保证在同一个bean中没有两个线程处于活动状态。

使用CDI,您可以通过将实体管理器封装在请求范围的bean中并将其注入到应用程序范围的bean中,从而对每个请求获得类似的效果:

import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@RequestScoped
public class EntityManagerProvider {

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

}

将其注入到之前注入实体管理器的bean中:

@Named
@ApplicationScoped
public class DAO {

   @Inject
   private EntityManagerProvider entityManagerProvider;

}

这将为每个请求提供唯一的实体管理器。您也可以轻松地将其转换为producer方法,这样就不必对注入的提供程序调用getEntityManager()

 类似资料:
  • 问题内容: 我打算用来将一些属性从应用程序层(特别是消息驱动的Bean)传递到不能直接注入或传递参数的持久性生命周期回调(EclipseLink中的会话侦听器,实体生命周期回调等),并且该回调通过JNDI 获取。 这似乎可以正常工作,但是我是否缺少任何隐藏的陷阱,例如线程安全性或对象寿命?(假设要传递的属性值是不变的,如String或Long。) 样本豆代码 然后使用EJBContext的回调 我

  • 问题内容: 我对SQL和锁定策略有疑问。例如,假设我在我的网站上有一个图片计数器。如果我有一个sproc或类似的东西来执行以下语句: 假设在时间t0特定image_id的计数器的值为‘0’。如果两个会话从t0同时开始更新同一个图像计数器s1和s2,则这两个会话都有可能都读取值‘0’,将其增加为‘1’,并且都尝试将计数器更新为‘1 ‘,那么计数器将获得值‘1’而不是‘2’? 最终结果:image_i

  • BECOMING SECURE AND ANONYMOUS 今天,几乎我们在互联网上做的一切都被跟踪。无论是谷歌跟踪我们的在线搜索、网站访问和电子邮件,还是美国国家安全局(NSA)对我们的所有活动进行编目,无论谁在跟踪我们,我们的每一次在线活动都会被记录、编入索引,然后被挖掘出来,以造福他人。普通个人,尤其是黑客,需要了解如何限制这种跟踪,并在网上保持相对匿名,以限制这种无处不在的监视。 在本章中

  • 问题内容: 我有一堂课 然后,我将在其他类的字段中引用Item 可以安全发布此 新Item 对象吗?如果没有,为什么?根据Java Concurrency in Practice,在 未完全构建 新项目的情况下发布了新项目,但在我看来,新项目已被完全构建:它的引用不会转义,并且对它及其状态的引用是同时发布的,因此使用者线程将看不到过时的值。还是可见性问题。我不知道原因。 问题答案: 可以安全发布此

  • WildFly中安全域和安全域的主要区别是什么? 独立的。xml 和

  • 问题内容: 刚收到安全审核的结果-除两件事外,其他一切都清晰可见 没有http标志的会话cookie。 没有设置安全标志的会话cookie。 该应用程序是用php编码的,修复建议为: 使用仅http标志设置会话cookie 使用安全标志设置会话cookie 我看过一些示例,但并不完全了解如何在Linux服务器上实现。我无权访问 .ini 文件。是否可以在htaccess文件中进行设置? 或者,如何