spring与设计模式之一工厂模式

发布时间 2024-01-07 15:43:28作者: 正在战斗中

大家都说要多阅读spring的代码,这非常在理,毕竟spring的代码是许许多多杰出工程师的结晶,是业界多年的累积。

最近也不是非常忙,所以准备记录一系列的相关代码。

工厂模式是所有人都会的模式,是最简单也最常用的模式。

为什么称为工厂模式,因为这个完全是借鉴实际产生的一种模式。

  1. 通过工厂模式,可以简化采购商(用户)的工作,也能够简化工厂的工作。
  2. 对于用户而言,只需要关心要什么,不需要重点关心如何生产;对于工厂(设计人员)而言,只需要关注如何实现,并把产品放在货架上即可。
  3. 工厂的产品之间可以有相似性(通常),但也允许没有任何的关系。例如一个商场可以卖食品也可以卖衣服、家具等等。当然为了方便,有专门卖食品、衣服、家具的

如果不用工厂模式会怎么样?其实也不会怎么样,就是不那么方便,这种不方便可大可小。

所以,总体来说能用就用。

本文不会介绍bean工厂的每个产品是如何定义的,这是因为spring的bean工厂是杂货铺,什么类型都有的,所以介绍有什么产品没有什么意义。

在spring中,很多地方都有工厂模式的应用,比较典型的就是bean工厂。

一、bean工厂类层次

所有的bean工厂的实现都基于BeanFactory这个接口,下图是spring6.x中默认bean工厂的类层次图:

也就是说默认情况下spring6.x实现的bean工厂是 DefaultListableBeanFactory(org.springframework.beans.factory.support.DefaultListableBeanFactory)。

反过来说,在spring中有多个的bean工厂实现。

二、DefaultListableBeanFactory的数据结构

以下是DefaultListableBeanFactory的部分代码:

@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    @Nullable
    private static Class<?> javaxInjectProviderClass;

    static {
        try {
            javaxInjectProviderClass =
                    ClassUtils.forName("jakarta.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - Provider interface simply not supported then.
            javaxInjectProviderClass = null;
        }
    }


    /** Map from serialized id to factory instance. */
    private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
            new ConcurrentHashMap<>(8);

    /** Optional id for this factory, for serialization purposes. */
    @Nullable
    private String serializationId;

    /** Whether to allow re-registration of a different definition with the same name. */
    private boolean allowBeanDefinitionOverriding = true;

    /** Whether to allow eager class loading even for lazy-init beans. */
    private boolean allowEagerClassLoading = true;

    /** Optional OrderComparator for dependency Lists and arrays. */
    @Nullable
    private Comparator<Object> dependencyComparator;

    /** Resolver to use for checking if a bean definition is an autowire candidate. */
    private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;

    /** Map from dependency type to corresponding autowired value. */
    private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

    /** Map of bean definition objects, keyed by bean name. */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    /** Map from bean name to merged BeanDefinitionHolder. */
    private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);

    /** Map of singleton and non-singleton bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

    /** Map of singleton-only bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

    /** List of bean definition names, in registration order. */
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

    /** List of names of manually registered singletons, in registration order. */
    private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

    /** Cached array of bean definition names in case of frozen configuration. */
    @Nullable
    private volatile String[] frozenBeanDefinitionNames;

    /** Whether bean definition metadata may be cached for all beans. */
    private volatile boolean configurationFrozen;
}

和所有的工厂类类似,DefaultListableBeanFactory也有货架(保存商品/实例)的属性,这里还挺多的:

beanDefinitionMap

allBeanNamesByType

singletonBeanNamesByType

。。。

更多代码略。

spring在初始化的时候,会往这些数据结构中塞入有关的数据(bean名称和对应的实例等等).

---

三、其它代码

其它代码是为了实现工厂完备所需要的一些非核心(相对工厂概念而言)代码,内容还是挺多的。

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/support/DefaultListableBeanFactory.html

 

在实际编码的时候,如果不想过多发挥,那么直接适用适用Bean工厂的工具类获取当前的bean工厂即可,并利用工厂提供的各种丰富功能实现诸如:

1.注册bean

2.下架bean

3.罗列bean

..