上一篇咱们结合Spring介绍了设计模式中的工厂模式相关方法,其实现在Java开发基本上都是基于Spring框架开发,所以后续我们在开发过程中基本上很少自己重写一个工厂模式,都是直接使用Spring来完成。今天咱们接着看剩下的创建型设计模式:单例、原型、建造者。
单例模式在Spring中的应用详解
单例模式确保一个类只有一个实例,并提供一个全局访问点。Spring框架默认情况下对所有Bean使用单例模式,即一个Bean只会被创建一次,并在整个Spring容器中共享。
1. 单例模式概述
单例模式包含以下角色:
- 单例类:定义一个私有的构造函数,确保只能通过静态方法获取唯一实例。
- 静态方法:提供获取单例实例的全局访问点。
2. 单例模式在Spring中的实现
源码分析:之前Spring源码相关内容已经分析过了这边直接贴代码来
Spring中的DefaultSingletonBeanRegistry
类实现了单例模式。该类维护了一个缓存,用于存储单例Bean实例。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);@Overridepublic Object getSingleton(String beanName) {return this.singletonObjects.get(beanName);}protected void addSingleton(String beanName, Object singletonObject) {this.singletonObjects.put(beanName, singletonObject);}
}
在Spring容器初始化过程中,当一个Bean被创建时,如果其作用域为单例(默认情况),Spring会调用addSingleton
方法将该Bean实例放入singletonObjects
缓存中。在以后每次请求该Bean时,Spring会从缓存中直接返回该实例,而不再创建新的实例。
原型模式在Spring中的应用详解
原型模式通过克隆现有的对象来创建新对象。Spring支持原型作用域(prototype),每次请求一个原型作用域的Bean时,都会创建一个新的实例。
1. 原型模式概述
原型模式包含以下角色:
- 原型接口:定义一个克隆方法。
- 具体原型类:实现克隆方法,返回自身的一个副本。
2. 原型模式在Spring中的实现
源码分析:
在Spring中,通过配置Bean的作用域为prototype
来实现原型模式。在DefaultListableBeanFactory
中,处理原型作用域的代码如下:
// 如果是原型beanelse if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {// 实例化前置准备工作beforePrototypeCreation(beanName);// 开始实例化prototypeInstance = createBean(beanName, mbd, args);}finally {// 实例化以后的处理工作afterPrototypeCreation(beanName);}// 获取原型bean实例对象bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}
这里可以明显的看到如果是原型模式,Spring会直接调用createBean而不会从单例缓存池中获取。
构建者模式在Spring中的应用详解
构建者模式通过逐步构建复杂对象,允许创建者一步步构建其表示。Spring中的BeanDefinitionBuilder
类使用了构建者模式,用于动态创建Bean定义。
1. 构建者模式概述
构建者模式包含以下角色:
- 构建者:提供构建复杂对象的各个方法。
- 具体构建者:实现构建者接口,构建具体的复杂对象。
- 指导者:指导构建者如何构建复杂对象。
- 产品:最终构建的复杂对象。
2. 构建者模式在Spring中的实现
源码分析:
Spring中的BeanDefinitionBuilder
类使用了构建者模式:
public class BeanDefinitionBuilder {private AbstractBeanDefinition beanDefinition;private BeanDefinitionBuilder(Class<?> beanClass) {this.beanDefinition = new GenericBeanDefinition();this.beanDefinition.setBeanClass(beanClass);}public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {return new BeanDefinitionBuilder(beanClass);}public BeanDefinitionBuilder addPropertyValue(String name, Object value) {this.beanDefinition.getPropertyValues().add(name, value);return this;}public AbstractBeanDefinition getBeanDefinition() {return this.beanDefinition;}
}
使用BeanDefinitionBuilder
时,可以通过链式调用逐步设置Bean的各个属性,最终调用getBeanDefinition
方法获取构建的Bean定义。例如:
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
builder.addPropertyValue("name", "testName").addPropertyValue("age", 30);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
通过上述详细分析,我们可以看到Spring框架在其设计和实现中广泛应用了单例模式、原型模式和构建者模式。这些设计模式不仅提高了代码的可维护性和可扩展性,还使得Spring框架能够灵活地管理对象的创建和依赖注入。
当然实际生产中,我们业务处理的类基本上都是交给Spring管理的如Service、Controller、Mapper等,这些类默认情况下都是单例,当我指定作用域为Prototype的时候,其实就是走了不同的判断逻辑,然后每次都需要重新创建。