Spring单例Bean与单例模式的区别

Spring单例Bean与单例模式的区别在于它们关联的环境不一样,单例模式是指在一个JVM进程中仅有一个实例,而Spring单例是指一个Spring Bean容器(ApplicationContext)中仅有一个实例。

首先看单例模式,在一个JVM进程中(理论上,一个运行的JAVA程序就必定有自己一个独立的JVM)仅有一个实例,于是无论在程序中的何处获取实例,始终都返回同一个对象,以Java内置的Runtime为例(现在枚举是单例模式的最佳实践),无论何时何处获取,下面的判断始终为真:

//  基于懒汉模式实现
//  在一个JVM实例中始终只有一个实例
Runtime.getRuntime() == Runtime.getRuntime()

与此相比,Spring的单例Bean是与其容器(ApplicationContext)密切相关的,所以在一个JVM进程中,如果有多个Spring容器,即使是单例bean,也一定会创建多个实例,代码示例如下:

//  第一个Spring Bean容器
ApplicationContext context_1 = new FileSystemXmlApplicationContext("classpath:/ApplicationContext.xml");
Person yiifaa_1 = context_1.getBean("yiifaa", Person.class);
//  第二个Spring Bean容器
ApplicationContext context_2 = new FileSystemXmlApplicationContext("classpath:/ApplicationContext.xml");
Person yiifaa_2 = context_2.getBean("yiifaa", Person.class);
//  这里绝对不会相等,因为创建了多个实例
System.out.println(yiifaa_1 == yiifaa_2);

以下是Spring的配置文件:

<!-- 即使声明了为单例,只要有多个容器,也一定会创建多个实例 -->
<bean id="yiifaa" class="com.stixu.anno.Person" scope="singleton">
    <constructor-arg name="username">
        <value>yiifaa</value>
    </constructor-arg>
</bean>

总结

Spring的单例bean与Spring bean管理容器密切相关,每个容器都会创建自己独有的实例,所以与GOF设计模式中的单例模式相差极大,但在实际应用中,如果将对象的生命周期完全交给Spring管理(不在其他地方通过new、反射等方式创建),其实也能达到单例模式的效果。

### Spring单例模式 Bean 初始化 在Spring框架内,单例模式下的Bean在整个应用上下文中仅存在一个实。当Spring容器启动时,会创建此类Bean的唯一实并将其存入IoC容器中以便后续使用[^3]。 #### Bean初始化过程 1. **实化** 实化的目的是为了创建一个新的Java对象。对于作用域内的Bean而言,在ApplicationContext加载期间即完成此步骤。通常情况下,Spring利用反射机制来构建目标类的新实[^4]。 2. **属性填充** 完成实化之后,紧接着就是设置Bean的各项属性值。这一步骤涉及到依赖注入(Dependency Injection),可以采用构造器注入、Setter方法注入或是字段级(@Autowired)的方式向新创建的对象赋予必要的协作组件或配置参数。 3. **初始化前处理** 如果有注册了`InstantiationAwareBeanPostProcessor`类型的后处理器,则在此阶段对其进行前置处理逻辑的操作。比如可以通过重写其相应的方法来进行一些额外的数据验证工作或者修改即将被初始化的对象状态等。 4. **初始化** 接下来进入真正的初始化环节。此时如果有实现特定接口(如`InitializingBean`),则调用其中定义好的初始化方法;另外还可以通过XML文件中的init-method属性指定某个普通成员函数作为自定义初始化入口点。值得注意的是,在这一过程中还可能会触发AOP代理对象生成等一系列复杂的内部操作。 5. **初始化后处理** 同样地,若有配置了`BeanPostProcessor`类型的服务提供者,则会在当前Bean完全准备好之前再次给予干预的机会——执行postProcessAfterInitialization()回调函数。 6. **加入到缓存池** 经过上述一系列准备活动以后,最终形成的Bean会被放置于专门维护着所有已知对象引用列表之中等待其他地方按需获取访问权限。 7. **销毁** 当应用程序结束运行或者是显式地关闭掉Application Context的时候,才会真正触及到Bean的终结时刻。按照既定顺序依次检查是否存在标注了`@PreDestroy`注解的方法、实现了`DisposableBean`接口的情况以及指定了destroy-method选项的情形,并据此作出相应的清理动作以确保资源得到妥善回收[^5]。 ```java // 示代码:定义一个简Bean @Component public class MySingletonBean { private String message; @Autowired public void setMessage(String message){ this.message = message; } // 可选:定义初始化方法 @PostConstruct public void init(){ System.out.println("MySingletonBean is initialized."); } // 可选:定义销毁方法 @PreDestroy public void destroy(){ System.out.println("MySingletonBean will be destroyed."); } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值