深入Spring专题(18)

95 阅读2分钟

这是我参与2022首次更文挑战的第24天,活动详情查看2022首次更文挑战

使用@Scope定义原型实例

@Component("nonSingleton")
@Scope("prototype")
public class Singer{
    
    private String name="unknown";
    
    public Singer(@Value("Tony") String name){
        this.name=name;
    }
    
    public void sing(){
        System.out.println(name);
    }
}

Spring默认作用域为singleton值,原型作用域指示Spring在每次应用请求bean实例时实例化一个新的bean实例。

public class NonSingleton{
    public static void main(String... args){
        GenericXmlApplication ctx=new GenericXmlApplicationContext();
        ctx.load("classpath:spring/app-context.xml");
        ctx.refresh();
        
        Singer singer1=ctx.getBean("nonSingleton",Singer.class);
        Singer singer2=ctx.getBean("nonSingleton",Singer.class);
        
        System.out.println("Identity Equal:"+(singer1 == singer2));
        System.out.prinln("Value Equal:"+singer1.equals(singer2));
        System.out.println(singer1);
        System.out.println(singer2);
        
        ctx.close();
    }
}

运行输出结果如下:

Identity Equal:false
Value Equal:false
Tony
Tony

由此看出,虽然两个String对象的值相等,但是身份不同,即使两个实例使用相同的bean名称进行检索。

选择实例化模式

单例是bean的默认模式,单例在下列情况下使用:

  • 没有状态的共享对象:如果有一个不保持状态且有许多依赖对象的对象,因为如果没有状态不需要同步,所以每次依赖对象需要使用该对象进行一些处理时,不需要创建bean的新实例。
  • 具有只读状态的共享对象:有一些只读状态,但仍然不需要同步,所以创建一个实例来满足bean的每个请求只会增加开销。
  • 具有共享状态的共享对象:如果有一个必须共享状态的bean,那单例是最理想的选择,在这种情况下,确保状态写入同步尽可能细化。
  • 具有可写状态的高通量对象

在下列情况使用非单例:

  • 具有可写状态的对象:如果有一个拥有大量可写状态的bean,保持同步所需的成本大于创建新实例以处理来自依赖对象的每个请求的成本。
  • 具有私有状态的对象:某些依赖对象需要具有私有状态的bean,以便他们可与依赖于该bean的其他对象分开进行处理。