我写的这些类是否在线程安全性方面有所破坏? ManagedBeans是否在不同的Threads中使用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我写的这些类是否在线程安全性方面有所破坏? ManagedBeans是否在不同的Threads中使用?相关的知识,希望对你有一定的参考价值。

我在这里写了这门课

@Component
public class LoginDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<Map<String, Object>> getUser(final String username, final String password) {
        return jdbcTemplate.queryForList("select * from users where username=? and password=?", new Object[]{username, password});
    }
}

现在,它由JSF中的managedbean使用,它只是在创建请求时创建并使用的bean(如果使用默认范围)。

@ManagedBean
public class Login implements Serializable {
    @ManagedProperty("#{loginDao}")
    private LoginDao loginDao;
//..do something with loginDao
}

我很害怕这完全被破坏了,因为如果JSF创建的Login bean使用了loginDao,这是一个注入的对象,并且看到loginDao的字段jdbcTemplate为null?

如果用于处理请求的Login bean将在单独的线程中运行,如果Web服务器使用该单独的线程来处理该请求,并且由于LoginDao的字段jdbcTemplate不是final,并且在运行之前在构造函数中设置,则可能会发生这种情况。登录bean,在Login实例中,jdbcTemplate不能被视为null吗?解决这个问题的方法是使jdbcTemplate变得易变吗?

此外,现在这让我质疑我用spring和JSF编写的所有内容。除非在该字段上使用volatile关键字,否则在使用@Autowired批注时编写线程安全类是不可能的?

我现在真的很担心使用依赖注入框架。我的意思是,是否有保证容器注入的对象不会被视为null引用或非最新状态?

答案

在初始化期间注入自动装配的bean,因此在这种情况下,处理请求时jdbcTemplate永远不应为null。但是,如果你想完全确定,你可以通过构造函数注入它,这是推荐的方法:

@Component
public class LoginDao {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public LoginDao(JdbcTemplate jdbcTemplate) {
      this.jdbcTemplate = jdbcTemplate;
    }

    public List<Map<String, Object>> getUser(final String username, final String password) {
        return jdbcTemplate.queryForList("select * from users where username=? and password=?", new Object[]{username, password});
    }
}

正如您所说,很有可能多个请求将由不同的线程处理,并且会发生什么完全取决于定义的范围:

  • spring中的默认范围是“singleton”,因此在这种情况下,LoginDAO将只在应用程序中有一个服务所有请求的实例。在您发布的代码中,这不是问题,因为JdbcTemplate是线程安全的。

此外,现在这让我质疑我用spring和JSF编写的所有内容。除非在该字段上使用volatile关键字,否则在使用@Autowired批注时编写线程安全类是不可能的?

它完全有可能。它主要取决于你需要的东西。您可以拥有一个以线程安全的方式执行其操作的单例bean(依赖于您的代码和您使用的库),或者您可以让非线程安全bean使用“请求范围”(即:一个bean实例)对于每个请求),或中间的任何东西(春天有5种范围类型)。

如果出于完全不同的目的,将字段设置为易失性。 volatile关键字表示字段值将被多个线程连续修改,因此JVM不会在线程内缓存其值以防止竞争条件,并将以原子方式管理asignations。这只会保护字段值,但如果值是对象,则不会保护该对象内的值。

我现在真的很担心使用依赖注入框架。我的意思是,是否有保证容器注入的对象不会被视为null引用或非最新状态?

至少在我的春季经历中,我从未遇到过这个问题。 Spring在启动时初始化准备一切都很好,所以你不必担心这一点。但是,建议使用之前指示的构造函数自动装配方法,因为这样可以使程序员更准确地了解您的问题。

以上是关于我写的这些类是否在线程安全性方面有所破坏? ManagedBeans是否在不同的Threads中使用?的主要内容,如果未能解决你的问题,请参考以下文章

对象的组合

从另一个线程发出信号是否安全?

线程安全性详解

Java中的String,StringBuilder,StringBuffer三者的区别

Java中的String,StringBuilder,StringBuffer三者的区别

Java中的String,StringBuilder,StringBuffer三者的区别