三级接口:ConfigurableBeanFactory 配置Bean工厂【巨大的工厂接口】
对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry(因此它也具有分层、注册单例Bean的能力了)。
SingletonBeanRegistry:Spring容器对单例bean实例的登记管理主要通过接口SingletonBeanRegistry建模抽象,我们可以称之为"单例bean实例注册表"。
public interface SingletonBeanRegistry { //以指定的名字将给定Object注册到BeanFactory中。 //此接口相当于直接把Bean注册,所以都是准备好了的Bean。(动态的向容器里直接放置一个Bean) //什么BeanPostProcessor、InitializingBean、afterPropertiesSet等都不会被执行的,销毁的时候也不会收到destroy的信息 void registerSingleton(String beanName, Object singletonObject); //以Object的形式返回指定名字的Bean,如果仅仅还是只有Bean定义信息,这里不会反悔 // 需要注意的是:此方法不能直接通过别名获取Bean。若是别名,请通过BeanFactory的方法先获取到id @Nullable Object getSingleton(String beanName); //是否包含此单例Bean(不支持通过别名查找) boolean containsSingleton(String beanName); // 得到容器内所有的单例Bean的名字们 String[] getSingletonNames(); int getSingletonCount(); // @since 4.2 // 获取当前这个注册表的互斥量(mutex),使用者通过该互斥量协同访问当前注册表 // 实现类DefaultSingletonBeanRegistry就一句话:return this.singletonObjects; 返回当前所有的单例Bean Object getSingletonMutex(); }
ConfigurableBeanFactory中定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory,bean如何销毁【共55+个方法,虽然方法繁多,还算井井有条】
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { //定义了两个作用域: 单例和原型.可以通过registerScope来添加. String SCOPE_SINGLETON = "singleton"; String SCOPE_PROTOTYPE = "prototype"; //父容器设置.而且一旦设置了就不让修改(改就抛错) // 配合父接口HierarchicalBeanFactory的getParentBeanFactory方法 void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException; //类加载器设置与获取.默认使用当前线程中的类加载器 void setBeanClassLoader(@Nullable ClassLoader beanClassLoader); @Nullable ClassLoader getBeanClassLoader(); //为了类型匹配,搞个临时类加载器.好在一般情况为null,使用上面定义的标准加载器 void setTempClassLoader(@Nullable ClassLoader tempClassLoader); @Nullable ClassLoader getTempClassLoader(); //设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加载) // 在字段mergedBeanDefinitions里存着,和getMergedBeanDefinition方法有关 void setCacheBeanMetadata(boolean cacheBeanMetadata); boolean isCacheBeanMetadata(); //定义用于解析bean definition的表达式解析器 void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver); @Nullable BeanExpressionResolver getBeanExpressionResolver(); //类型转化器 void setConversionService(@Nullable ConversionService conversionService); @Nullable ConversionService getConversionService(); //添加一个属性编辑器的登记员:Registrar void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar); //注册常用属性编辑器 void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass); //用工厂中注册的通用的编辑器初始化指定的属性编辑注册器 void copyRegisteredEditorsTo(PropertyEditorRegistry registry); //BeanFactory用来转换bean属性值或者参数值的自定义转换器 void setTypeConverter(TypeConverter typeConverter); TypeConverter getTypeConverter(); //string值解析器(想起mvc中的ArgumentResolver了) //增加一个嵌入式的StringValueResolver void addEmbeddedValueResolver(StringValueResolver valueResolver); // 上面增加过,这里就是true嘛 boolean hasEmbeddedValueResolver(); // 用注册的值解析器,依次解析这个value(注意是依次解析)。谁先解析出为null了,后面就不再解析了 @Nullable String resolveEmbeddedValue(String value); // 向工厂里添加Bean的后置处理器BeanPostProcessor // 需要注意的是:内部实现是先执行remove,再add的设计技巧 void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); int getBeanPostProcessorCount(); // 作用域定义:注册范围 void registerScope(String scopeName, Scope scope); String[] getRegisteredScopeNames(); @Nullable Scope getRegisteredScope(String scopeName); //访问权限控制:返回本工厂的一个安全访问上下文 和java.security有关的 AccessControlContext getAccessControlContext(); //从其他的工厂复制相关的所有配置 void copyConfigurationFrom(ConfigurableBeanFactory otherFactory); //给指定的Bean注册别名 内部还会checkForAliasCircle(name, alias); void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException; void resolveAliases(StringValueResolver valueResolver); //合并bean定义,包括父容器的 返回合并后的Bean定义信息 BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; //是否是FactoryBean类型 判断指定Bean是否为一个工厂Bean boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException; //bean创建状态控制.在解决循环依赖时有使用 设置一个Bean是否正在创建 void setCurrentlyInCreation(String beanName, boolean inCreation); boolean isCurrentlyInCreation(String beanName); //处理bean依赖问题 //注册一个依赖于指定bean的Bean void registerDependentBean(String beanName, String dependentBeanName); //返回依赖于指定Bean的所欲Bean名 String[] getDependentBeans(String beanName); //返回指定Bean依赖的所有Bean名(注意和上面的区别,是反过来的) String[] getDependenciesForBean(String beanName); // 销毁的相关方法 void destroyBean(String beanName, Object beanInstance); void destroyScopedBean(String beanName); //销毁所有的单例们 void destroySingletons(); }
这个工厂名为ConfigurableBeanFactory,真是名不虚传。功能也不可为不强大
四级接口:ConfigurableListableBeanFactory Bean工厂的集大成者
它是一个更强大的接口,继承了上述的所有接口,无所不包。
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { // 忽略的自动注入的类型。也就是说这些类型不能@Autowired了 void ignoreDependencyType(Class<?> type); // 忽略自动装配的接口 void ignoreDependencyInterface(Class<?> ifc); // 注册一个可以给解析的依赖。这样子注入进去的,在Autowired的时候就可以被自动注入进去了,即使不在容器里面 void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue); //判断指定的Bean是否有资格作为自动装配的候选者 boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException; //返回注册的Bean定义(这个比较常用) 它可以拿到单独的某个Bean定义信息 // ListableBeanFactory都是批量的返回 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; Iterator<String> getBeanNamesIterator(); // 清理元数据的缓存 void clearMetadataCache(); //暂时冻结所有的Bean配置 void freezeConfiguration(); boolean isConfigurationFrozen(); // 这个厉害了:实例化当前所有的剩下的单实例Bean们 void preInstantiateSingletons() throws BeansException; }
加上自有的这8个方法,这个工厂接口总共有80+个方法,实在是巨大到不行了,所以它是集大成者。
上面介绍的全部是工厂接口,那么接下俩,就开始介绍接口的抽象类实现了。========
抽象类工厂(一级):AbstractBeanFactory
AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory(方法50+的接口)大部分功能。
而且继承自FactoryBeanRegistrySupport,所以它也具备了SingletonBeanRegistry和SimpleAliasRegistry的能力
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { ... 实现了大部分的方法,其中最终的实现为getBean()/doGetBean()方法的实现,提供了模版。其实createBean抽象方法,还是子类去实现的 ... isSingleton(String name) / isPrototype(String name) / containsBean(String name) 也能实现精准的判断了 // ===其中,它自己提供了三个抽象方法,子类必要去实现的=== // 效果同:ListableBeanFactory#containsBeanDefinition 实现类:DefaultListableBeanFactory protected abstract boolean containsBeanDefinition(String beanName); // 效果同:ConfigurableListableBeanFactory#getBeanDefinition 实现类:DefaultListableBeanFactory protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException; // 创建Bean的复杂逻辑,子类去实现。(子类:AbstractAutowireCapableBeanFactory) protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException; }
此处Spring其实用了一个小技巧:采用抽象方法和接口方法签名一模一样。比如这里的containsBeanDefinition和getBeanDefinition等。这样的好处是,子类若同时实现对应接口、抽象类等,能够达到类似:跨级实现的效果~~~(我明明没有实现它这个接口,但我却复写了这个接口的方法…)
抽象类工厂(二级):AbstractAutowireCapableBeanFactory
实例化bean和依赖注入是在AbstractBeanFactory的入口,但是实际还是在AbstractAutowireCapableBeanFactory这个类中实现。(入口是getBean()方法)
// 继承自抽象实现:AbstractBeanFactory public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { // 它有很多属性,我觉得还是很有意义的 // Bean的实例化需要借助它,策略接口 private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); // 解析方法参数的名字 @Nullable private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); // 这两个保存的类型,是ignore on dependency check and autowire(字段装配时,如果在这里面的类型讲被忽略) // 使用:我们可以自己忽略类型:beanFactory.ignoreDependencyType(ArrayList.class); 比如在BeanFactoryPostProcessor 这里可以这么做 // 他们有些区别:因为平时使用较少,却别这里就不详细介绍了 // 总之,若你自己想忽略特定类型的自动注入的话,推荐使用ignoredDependencyTypes private final Set<Class<?>> ignoredDependencyTypes = new HashSet<>(); private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>(); ... 最重要的是实现了doCreateBean()的创建逻辑,然后执行队形的BeanPostProcessor ... applyPropertyValues():这里做的大部分工作就是依赖的准备工作 ... 然后对bean实例化、初始化、并完成了它的依赖注入入口(具体逻辑由子类DefaultListableBeanFactory具体去实现) ... 它实现了对Bean的实例化、populateBean()、以及initializeBean(),会对Bean进行注入等操作 ... 当然也管理了一些ignoredDependencyTypes,忽略的依赖等等 }
实例工厂类:DefaultListableBeanFactory Spring内部的唯一使用的工厂实现(XmlBeanFactory已废弃)基于bean definition对象,是一个成熟的bean factroy
默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,基于bean definition对象,**是一个成熟的bean factroy。**它是整个bean加载的核心部分,也是spring注册加载bean的默认实现
DefaultListableBeanFactory既可以作为一个单独的beanFactory,也可以作为自定义beanFactory的父类。
至于特定格式的Bean定义信息(比如常见的有xml、注解等)的解析器可以自己实现,也可以使用原有的解析器,如: PropertiesBeanDefinitionReader和XmLBeanDefinitionReader、AnnotatedBeanDefinitionReader
// extends:相当于继承了抽象类所有的实现,并且是已经具有注入功能了(含有ListableBeanFactory、ConfigurableListableBeanFactory的所有接口) // implements:直接实现ConfigurableListableBeanFactory,表示它具有了批量处理Bean、配置Bean等等功能 // BeanDefinitionRegistry:该接口目前还仅有这个类实现(它父接口为:AliasRegistry ) public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { }
BeanDefinitionRegistry接口简介: 定义了一些对 bean的常用操作
public interface BeanDefinitionRegistry extends AliasRegistry { // 注册一个Bean定义信息(下面的方法都非常的简单,就不一一介绍了) void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; boolean containsBeanDefinition(String beanName); String[] getBeanDefinitionNames(); int getBeanDefinitionCount(); boolean isBeanNameInUse(String beanName); // 需要注意的是:这里面有写方法和ListableBeanFactory接口里定义的三个关于Bean定义的方法一样的: //getBeanDefinitionNames/getBeanDefinitionCount等等 }
为什么要拆成这么多的类和接口呢。这里面可能基于几点考虑:
- 功能的不同维度,分不同的接口,方便以后的维护和其他人的阅读。(代码的可读性异常的重要,特别像Spring这种持久性的项目)
- 不同接口的实现,分布在不同的之类里,方便以后不同接口多种实现的扩展(单一职责,才好扩展。否则造成臃肿后,后面无法发展)
- 从整个类图的分布,可以看出spring在这块是面向接口编程,后面类的实现,他们认为只是接口功能实现的一种,随时可以拓展成多种实现 (面向接口编程,能极大的解耦各模块之间的互相影响)
ApplicationContext体系
如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的躯体了,ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现
ApplicationContext接口继承众多接口,集众多接口功能与一身,为Spring的运行提供基本的功能支撑。
根据程序设计的“单一职责原则”,其实每个较顶层接口都是“单一职责的”,只提供某一方面的功能,而ApplicationContext接口继承了众多接口,相当于拥有了众多接口的功能
下面我们看看ApplicationContext体系的家族图标(提供一个web环境的和一个非web环境的):
web环境的如下(XmlWebApplicationContext、GroovyWebApplicationContext、AnnotationConfigWebApplicationContext):
非web环境下如:AnnotationConfigApplicationContext
、FileSystemXmlApplicationContext
、ClassPathXmlApplicationContext