Spring:这种模式是线程安全的吗?

5
我一直在学习如何使用Spring框架来处理hibernate事务管理,在这方面它确实帮了我很大的忙。但问题是最近我意识到,我没有考虑过所选择的模式如何处理并发,特别是在Web应用程序的情况下。
以下是我正在使用的示例代码,它是一些我找到的示例和自定义servlet实现的组合。我对这种模式的工作方式以及是否线程安全存在一些疑问,因为我对其进行了一些定制。其中一些问题包括:
  • 尽管servlets在技术上不是单例的,但我有一种印象,每个servlet类通常只会有一个实例。
  • 如果我理解正确,每个自动连接的属性将是单例的,因此,如果以上是真的,那么将有一个单个的servlet实例,其中包含一个单个的service实例,该实例又有一个单个的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);
    }
}

我这里没有看到具体的问题。就目前而言,这似乎是一个请求代码审查的要求。 - Raedwald
2个回答

4
如果您在Hibernate配置中设置了适当的策略,那么sessionFactory.getCurrentSession()将返回一个作用域会话,而不是全局会话。会话工厂旨在成为单例,这是完全正确的;getCurrentSession()是通常用于桥接到当前上下文范围的方法。
“适当的策略”因情况而异,但如果您正在使用Spring事务管理包装DAO,则会话的生命周期将是DAO方法调用的时间,并且Spring将在退出时协调调用提交/回滚。

谢谢。只要我按照Meriton说的,并且坚持使用Spring事务管理,这个模式就没问题。 - JayPea

3

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接