spring与设计模式之一工厂模式
大家都说要多阅读spring的代码,这非常在理,毕竟spring的代码是许许多多杰出工程师的结晶,是业界多年的累积。
最近也不是非常忙,所以准备记录一系列的相关代码。
工厂模式是所有人都会的模式,是最简单也最常用的模式。
为什么称为工厂模式,因为这个完全是借鉴实际产生的一种模式。
- 通过工厂模式,可以简化采购商(用户)的工作,也能够简化工厂的工作。
- 对于用户而言,只需要关心要什么,不需要重点关心如何生产;对于工厂(设计人员)而言,只需要关注如何实现,并把产品放在货架上即可。
- 工厂的产品之间可以有相似性(通常),但也允许没有任何的关系。例如一个商场可以卖食品也可以卖衣服、家具等等。当然为了方便,有专门卖食品、衣服、家具的
如果不用工厂模式会怎么样?其实也不会怎么样,就是不那么方便,这种不方便可大可小。
所以,总体来说能用就用。
本文不会介绍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
..