挠头~?加了@Scope(value="prototype")为

2020-01-10  本文已影响0人  风中的白乌鸦

挠头~?加了@Scope(value="prototype")为何还是单例?

例子
@Component
//配置bean作用域为多例
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ShellUtil{
    private static Connection conn = new Connection();
}
@RestController
public class ExecController {

    @Autowired
    private ShellUtil shell;
    
    @GetMapping("test")
    public void test(){
     System.out.println("Thaad-Name:"+Thread.currentThread().getName());
     System.out.println("ObjHashCode:"+shell.hashCode());
  }
)
    
执行结果:

拿到的还是同一个bean

???挠头~

分析:上面的例子中虽然ShellUtil虽然设置为了多例,但是他被单例对象ExecController依赖,ExecController在初始化Bean的时候ShellUtil已经注入,并且注入时只创建一次。

方法1
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@RestController
public class ExecController {

    @Autowired
    private ShellUtil shell;
    
    @GetMapping("test")
    public void test(){
     System.out.println("Thaad-Name:"+Thread.currentThread().getName());
     System.out.println("ObjHashCode:"+shell.hashCode());
  }
)
执行结果:

效果是达到了,但是ExecController失去了单例的优势,若bean的调用链很长则每个被依赖的bean都需要配置为多例。

方法2
@RestController
public class ExecController {

    /** 
    * 获取spring上下文 
    */
    @Autowired
    private WebApplicationContext applicationContext;
    
    @GetMapping("test")
     public void test() {
     System.out.println("Thaad-Name:"+Thread.currentThread().getName());
     System.out.println("ObjHashCode:"+shell.hashCode());
  }
)

执行结果:
方法3
@Component
public class ShellUtil{
    //使用ThreadLocal装配Connection对象
    private static ThreadLocal<Connection> conn = new ThreadLocal<>();
   
    public void close() {    
    if (conn != null) { 
        conn.get().close()
    //注意:连接关闭后,记得回收ThreadLocal对象
        conn.remove();            
    }
}


结论:
参考链接

https://www.cnblogs.com/heyanan/p/12054840.html

上一篇下一篇

猜你喜欢

热点阅读