【问题标题】:Spring: Is this pattern thread-safe? [closed]Spring:这种模式是线程安全的吗? [关闭]
【发布时间】:2011-12-07 18:26:16
【问题描述】:

我一直在学习如何使用 Spring 框架进行休眠事务管理,到目前为止,它对这个目的有很大帮助。问题是最近,我意识到我没有过多考虑我选择的模式如何处理并发,特别是在 Web 应用程序的情况下。

下面是示例我正在使用的模式的代码,它是我找到的一些示例和自定义 servlet 实现的组合。我对这种模式如何工作以及它是否是线程安全的有一些疑问,因为我对其进行了一些定制。我的一些担忧是:

  • 尽管 servlet 在技术上不是单例,但我的印象是大多数时候每个 servlet 类只有一个实例。
  • 如果我理解正确,每个自动连接的属性都将是一个单例,因此如果上述情况属实,那么将有一个带有单个服务实例的单个 servlet 实例,而该实例又具有一个 DAO 实例,它有自己的 SessionFactory 实例。
  • 如果以上是正确的,那么我可以想象 servlet 上的每个请求都将使用相同的对象,我想知道这是否是一件好事。经过一番思考,我不知道是线程安全是单例还是为每个 http 请求创建新实例更好。
  • 通常这些 spring 模式有一个 @Controller 类,我跳过了它以支持我们的自定义 servlet,我想知道这是否会以某种方式破坏模式的并发性。

谢谢

public interface UserDAO
{
    public void save(User user);
}

@Repository
public class HibernateUserDAO implements UserDAO
{
    @Autowired(required=true)
    protected SessionFactory sessionFactory;

    public void save(User user)
    {
        this.sessionFactory.getCurrentSession().save(user);
    }
}

public interface UserService
{
    public void saveUser(User user);
}

@Service
public class DefaultUserService implements UserService
{
    @Autowired(required=true)
    private UserDAO userDAO;

    @Transactional
    public void saveUser(User user)
    {
        this.userDAO.save(user);
    }
}

public class UserServlet extends CustomServlet
{   
    @Autowired(required=true)
    private UserService userService;

    public void init() throws ServletException
    {
        super.init();
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        //would call the appropriate method depending on parameters, etc.
        //simplified here for demonstration purposes
        this.userService.saveUser(user);
    }
}

【问题讨论】:

  • 我在这里没有看到具体的问题。事实上,这看起来像是一个代码审查请求。

标签: java hibernate spring web-applications thread-safety


【解决方案1】:

如果您在 Hibernate 配置中设置了合适的策略,那么 sessionFactory.getCurrentSession() 将返回一个 作用域 会话,而不是全局会话。会话工厂旨在成为单例,这是非常正确的; getCurrentSession() 是桥接到当前上下文范围的常用方法。

“合适的策略”各不相同,但如果您使用包装在 DAO 周围的 Spring 事务管理,那么会话将具有 DAO 方法调用的生命周期,并且 Spring 将在退出时适当地协调调用提交/回滚。

【讨论】:

  • 谢谢。所以这个模式只要按照 Meriton 说的,坚持 Spring 事务管理就可以了?
【解决方案2】:

默认情况下,Spring bean 在应用程序范围内,即您的应用程序中只有一个实例。您可以使用@Scope 更改它,但典型的模式是将它们保持在应用程序范围内并通过不在 bean 中存储任何状态来使它们成为线程安全的,即不应更改应用程序范围 bean 的所有字段,或引用对象在应用程序启动后更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 2012-12-18
    相关资源
    最近更新 更多