您的当前位置:首页正文

@Scope(“prototype“)的正确用法——解决Bean的多例问题

2024-11-30 来源:个人技术集锦

@Scope(“prototype“)的正确用法——解决Bean的多例问题

Spring管理的某个Bean需要使用多例

  • 在使用了Spring的web工程中,除非特殊情况,我们都会选择使用Spring的IOC功能来管理Bean,而不是用到时去new一个。Spring管理的Bean默认是单例的(即Spring创建好Bean,需要时就拿来用,而不是每次用到时都去new,又快性能又好),但有时候单例并不满足要求(比如Bean中不全是方法,有成员,使用单例会有线程安全问题,可以搜索线程安全与线程不安全的相关文章),你上网可以很容易找到解决办法,即使用@Scope(“prototype”)注解,可以通知Spring把被注解的Bean变成多例,如下所示:

  • import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping(value = "/testScope")
    public class TestScope {
    
        private String name;
    
        @RequestMapping(value = "/{username}",method = RequestMethod.GET)
        public void userProfile(@PathVariable("username") String username) {
            name = username;
            try {
                for(int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getId() + "name:" + name);
                    Thread.sleep(2000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }
    }
    
  • 分别发送请求http://localhost:8043/testScope/aaa和http://localhost:8043/testScope/bbb,控制台输出:

  • 34name:aaa
    34name:aaa
    35name:bbb
    34name:bbb
    
  • (34和35是两个线程的ID,每次运行都可能不同,但是两个请求使用的线程的ID肯定不一样,可以用来区分两个请求。)可以看到第二个请求bbb开始后,将name的内容改为了“bbb”,第一个请求的name也从“aaa”改为了“bbb”。要想避免这种情况,可以使用@Scope(“prototype”),注解加在TestScope这个类上。加完注解后重复上面的请求,发现第一个请求一直输出“aaa”,第二个请求一直输出“bbb”,成功。

显示全文