认识Bean工厂
- 一、认识Bean工厂
- BeanFactory
- ListableBeanFactory
- HierarchicalBeanFactory
- AutowireCapableBeanFactory
- ConfigurableBeanFactory
- ConfigurableListableBeanFactory
- 二、总结
一、认识Bean工厂
Spring Bean 工厂是Spring框架提供的一种机制,用于创建和管理对象(或称为Bean)。它是Spring框架的核心部分,提供了一种灵活、可配置的方式来管理对象的生命周期和依赖关系。
下面展示了整个 Bean 工厂的常见接口和类以及功能(其中 XmlBeanFactory 已经被弃用):
1、不同的接口展现了不同的能力,是对子类能力的抽象;
2、 抽象类构建通用方法的实现,是通用核心方法的具体实现;
3、 具体类完成特定功能的实现,是特定功能的具体实现;
BeanFactory
public interface BeanFactory {// 这个变量在获取一个 FactoryBean 的时候使用// 定义 FactoryBean 时的前缀String FACTORY_BEAN_PREFIX = "&";// 工厂的核心方法,提供了多种获取单个实例bean的能力// 有不同的获取方式:别名直接获取、别名+参数,根据对应构造获取、类型注入Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;// 返回对应的 ObjectProvider,这是一种可以延迟获取 bean 实例的模式// 比如基于 ObjectProvider#getIfUnique 方法获取实例(获取容器中的对象)<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);// 判断是否包含指定 name 的 bean Definition 或 单例// 此处返回 true 并不意味着 getBean 可以返回对应的实例boolean containsBean(String name);// 判断 name 对应的 bean 是否是单例boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 判断 name 对应的 bean 是否是原型(prototype)boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 判断指定 name 的bean是否匹配对应的类型boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;// 获取 name 对应的 bean 的类型@NullableClass<?> getType(String name) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;// 返回指定 name 的所有别名String[] getAliases(String name);}
在 Spring4.3 之前,我们的bean如果需要使用特定构造器进行构造时必须使用@Autowired注解:
@Service
public class UserService {private UserDao userDao;@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}
}
在 Spring4.3 之后,如果没有其他构造器(有无参构造默认会使用无参构造,当然如果无参也没有,还有多个有参),会隐式为其注入:
@Service
public class UserService {UserDao userDao;public UserService(UserDao userDao) {this.userDao = userDao;}
}
但是当容器中没有 UserDao 这个 Bean 的时候,就会报以下异常:
此时 ObjectProvider
就提供了它的作用了:
@Service
public class UserService {UserDao userDao;public UserService(ObjectProvider<UserDao> objectProvider) {// 如果容器中存在就返回,不存在返回nullthis.userDao = objectProvider.getIfUnique();}}
这样注入的好处很明显,就是如果容器中不存在 UserDao 或者存在多个 UserDao 时,可以从容处理。
ObjectProvider 接口如下,他继承自 ObjectFactory,这个接口后边也会常用:
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {T getObject(Object... args) throws BeansException;// 处理判断有可用的bean的时候我们怎么做,可以重写T getIfAvailable() throws BeansException;default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {T dependency = getIfAvailable();return (dependency != null ? dependency : defaultSupplier.get());}default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {T dependency = getIfAvailable();if (dependency != null) {dependencyConsumer.accept(dependency);}}// 处理判断只有唯一的bean的时候我们怎么做,可以重写T getIfUnique() throws BeansException;default T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {T dependency = getIfUnique();return (dependency != null ? dependency : defaultSupplier.get());}default void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {T dependency = getIfUnique();if (dependency != null) {dependencyConsumer.accept(dependency);}}// 当匹配多个时,可以迭代处理@Overridedefault Iterator<T> iterator() {return stream().iterator();}
}
ObjectFactory 作为一个对象工厂函数式接口更是简单:
@FunctionalInterface
public interface ObjectFactory<T> {/*** Return an instance (possibly shared or independent)* of the object managed by this factory.* @return the resulting instance* @throws BeansException in case of creation errors*/T getObject() throws BeansException;}
ListableBeanFactory
该工厂继承自 BeanFactory,在含有Bean基础功能的基础上,提供了更强的枚举能力。ListableBeanFactory 为后续的实现类提供了更强的枚举能力,这些能力可能不对外公开,但是对于子类操作容器的操作bean十分重要,下面是他提供的方法:
public interface ListableBeanFactory extends BeanFactory {// 对BeanDefinition的一些细节操作boolean containsBeanDefinition(String beanName);int getBeanDefinitionCount();String[] getBeanDefinitionNames();// 对 BeanFactory 中获取ObjectProvider方法的拓展<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit);<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit);// 获取指定类型(子类)的bean names// boolean includeNonSingletons 参数决定是否考虑 singleotn 以外的bean// boolean allowEagerInit 是否初始化对应FactoryBean,如果false则类型直接匹配对应的FactoryBeanString[] getBeanNamesForType(ResolvableType type);String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);String[] getBeanNamesForType(@Nullable Class<?> type);String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);/**基本同上,返回的 Map 结构k:beanNamev:beanInstance**/<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)throws BeansException;// 返回指定注解的beanName数组String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);// 返回指定注解的bean实例集合:beanName -> bean 实例Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;// 获取指定 beanName 上的注解// 同样涉及 FactoryBean 初始化的问题,由参数 allowFactoryBeanInit 决定@Nullable<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)throws NoSuchBeanDefinitionException;@Nullable<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)throws NoSuchBeanDefinitionException;<A extends Annotation> Set<A> findAllAnnotationsOnBean(String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)throws NoSuchBeanDefinitionException;
}
BeanFactory 的子接口:
- 拓展了枚举的能力,提供了多个枚举的方法;
- 这些方法都仅限于当前层级的枚举,如果需要考虑到父级,可以借助
BeanFactoryUtils
. containsBeanDefinition、getBeanDefinitionCount、getBeanDefinitionNames
这几个方法是完全基于当前 BeanFactory 中的 BeanDefinition 的,换句话说,对于通过 registerSingleton 等方法注册的 bean 实例,它们是不感知的。getBeanNamesForType、getBeansOfType
方法是会感知自行注册 bean 实例的,当然大多数场景的 bean 实例都是基于 BeanDefinition 扫描的。
HierarchicalBeanFactory
HierarchicalBeanFactory 为 bean 工厂提供了灵活的分层能力,这在 web 工程里由典型的应用,spring 和 springmvc 会建立两个独立的上下文,分层之后各司其职,更易管理。
public interface HierarchicalBeanFactory extends BeanFactory {// 返回 bean 工厂的父工厂@NullableBeanFactory getParentBeanFactory();// 此方法忽略祖先上下文定义的bean,只会查询本地工厂boolean containsLocalBean(String name);}
测试一手:
@Testpublic void testHierarchicalBeanFactory() {// 创建一个核心工厂DefaultListableBeanFactory parent = new DefaultListableBeanFactory();parent.registerSingleton("person1", new Person("张三", 18));// 创建一个子工厂工厂,独自管理各个层次的内容DefaultListableBeanFactory child = new DefaultListableBeanFactory();// 设置父子关联关系child.setParentBeanFactory(parent);// 子工厂可以访问父工厂的beanlog.info("{}", child.getBean("person1"));log.info("{}", child.containsBean("person1"));// containsLocalBean()方法判断当前工厂是否包含指定的bean,如果是,则返回true,否则返回falselog.info("{}", child.containsLocalBean("person1"));}
BeanFactory 的 子接口:
- 提供了层次关系维护,
getParentBeanFactory
用于获取父 BeanFactory - containsLocalBean 不同于 BeanFactory#containsBean,只会在当前层级中判断是否存在指定
name
的bean实例
.
AutowireCapableBeanFactory
这个接口提供了构建和自动装配的能力,主要是赋予子类自动装配的能力,是容器最核心的接口,这个接口定义了 bean 的创建以及装配能力,同时细粒度的控制了 bean 的生命周期。
public interface AutowireCapableBeanFactory extends BeanFactory {// 表示不进行自动注入,默认情况下都是该状态// 真正的注入,一般都是基于 @Autowire 等注解驱动int AUTOWIRE_NO = 0;// 基于属性 name 的自动注入模式,一般不用int AUTOWIRE_BY_NAME = 1;// 基于属性 type 的自动注入模式,@Bean 方式就是这种模式int AUTOWIRE_BY_TYPE = 2;// 基于构造方法的自动注入,一般不用int AUTOWIRE_CONSTRUCTOR = 3;// 通过此后缀获取原始实例(比如 代理实例的 target)String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";// 创建实例的典型方法<T> T createBean(Class<T> beanClass) throws BeansException;// 自动填充指定 bean 实例属性,本质上是 after-instantiation 和 property post-processing 回调的执行void autowireBean(Object existingBean) throws BeansException;// 配置给定 bean 实例,本质是属性填充以及初始化回调的执行Object configureBean(Object existingBean, String beanName) throws BeansException;//--------------------------------------------------------------------// 用于对bean生命周期进行细粒度控制的专门方法// 主要是三块内容:创建(实例化) 属性填充(装配) 初始化//--------------------------------------------------------------------/**生命周期第一步(创建)按照指定的装配策略根据class生成一个完整的bean的实例执行bean的完全初始化,包括所有适用的beanpostprocessors@param dependencyCheck 是否对对象执行依赖项检查(不适用于自动装配构造函数,因此忽略)@return 新的bean的实例**/Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;/**生命周期第二步(装配)基于 autowireMode 创建 bean 实例并自动填充通过应用 after-instantiation 和 property post-processing(例如注解驱动的注入)来填充给定的bean实例**/Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;/*** 基于 autowireMode 自动填充已经存在的 bean 实例* 已经存在的实例不支持 AUTOWIRE_CONSTRUCTOR */void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)throws BeansException;/*** 基于 BeanDefinition 的属性填充已存在的 bean 实例*/void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;// 初始化前的回调// 将 BeanPostProcessors 应用到给定的现有bean实例// 调用它们的postprocessBeforeInitialization方法Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException;// 初始化给定的原始 bean,应用工厂回调,如setBeanName和setBeanFactory// 当然也包括应用所有的bean postprocessorsObject initializeBean(Object existingBean, String beanName) throws BeansException;// 初始化后置处理Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException;// 销毁给定的bean实例// 使用DisposableBean接口定义的销毁方法void destroyBean(Object existingBean);//-------------------------------------------------------------------------// 解决匹配注入点的方法// 在注入的时候通过以下的方法匹配属性与之对应的bean//-------------------------------------------------------------------------/*** 解析唯一匹配给定对象类型(如果有的话)的bean实例,包括它的bean名称。* 比如我们调用getBean(User.class) 会匹配一个或多个bean,需要该方法进行选择* 这实际上是getBean(Class)的一个变体。*/<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;/*** 解析给定bean名称的bean实例, 向目标工厂方法公开提供依赖描述符。* 这实际上是getBean(String, Class)的一个变体,*/Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;/*** 针对此工厂中定义的bean解析指定的依赖项,注入的时候很有用。* 通过一个依赖的描述(对方法,字段,构造器的抽象),获得一个bean*/@NullableObject resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;}
BeanFactory 的 子接口:
- 拓展了 自动注入 等相关能力
- 它的能力被单独拎出来,因此允许非 Spring 组件的实例也借助它来实现自动装配;
- 它的功能没有暴露给
ApplicationContext
,但是在 ApplicationContext 上下文中,可以通过ApplicationContext#getAutowireCapableBeanFactory
获取该实例,当然也可以直接获取 BeanFactory 进行类型转换。 - 它定义了不同的粒度生命周期的相关方法,基于主要的几个里程碑比如 实例的创建 属性的填充 初始化回调 来划分,一般 Spring 内部自然是对 bean 实例执行全过程的生命周期。
ConfigurableBeanFactory
它是 HierarchicalBeanFactory
的子接口,在基础能力和分层能力之上拓展了配置能力,这是 Spring 常用的类设计模式,这一层抽象了所有 BeanFactory
类相关组件的维护,比如:
BeanExpressionResolver
:SpEL
解析器ConversionService
:转换服务TypeConverter
:类型转换的顶层接口,相当于整合了ConversionService
和PropertyEditorRegistry
BeanPostProcessor
:支持添加BeanPostProcessor
对bean实例
进行后处理- 等等
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {// 标准单例作用域的范围标识符:"singleton".自定义作用域可以通过 registerScope 添加String SCOPE_SINGLETON = "singleton";String SCOPE_PROTOTYPE = "prototype";// 设置此 bean 工厂的父级void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;// 将 classLoader 设置为加载中的 bean 类,默认是线程上下文类装入器void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);// 返回这个工厂的classLoader,用于加载bean类@NullableClassLoader getBeanClassLoader();/*** 指定一个临时ClassLoader用于类型匹配,默认为none。* 如果涉及到加载时织入,则通常只指定临时ClassLoader,以确保实际的bean类尽可能延迟地加载。* 一旦BeanFactory完成引导阶段,临时加载器就会被移除。*/void setTempClassLoader(@Nullable ClassLoader tempClassLoader);// 返回用于类型匹配的临时ClassLoader,ClassLoader getTempClassLoader();/**设置是否缓存bean元数据,例如给定的bean定义(以合并的方式)和 resolved bean classes关闭此标志可启动 bean Definition 和 特定bean类的热刷新如果该标志关闭,则任何bean实例的创建都将重新查询 bean class Loader 以获得新解析的类。**/void setCacheBeanMetadata(boolean cacheBeanMetadata);boolean isCacheBeanMetadata();// 设置和获取SpEL表达式解析器void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);@NullableBeanExpressionResolver getBeanExpressionResolver();// 设置和获取转化服务void setConversionService(@Nullable ConversionService conversionService);@NullableConversionService getConversionService();// 添加属性编辑器void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);void copyRegisteredEditorsTo(PropertyEditorRegistry registry);// 配置和获取类型转化器,相当于整合了 ConversationService 和 PropertyEditorRegistervoid setTypeConverter(TypeConverter typeConverter);TypeConverter getTypeConverter();// 为注入的值添加一个String解析器,如“aa${bb}cc”。void addEmbeddedValueResolver(StringValueResolver valueResolver);boolean hasEmbeddedValueResolver();String resolveEmbeddedValue(String value);// 添加和获取bean的后置处理器void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);int getBeanPostProcessorCount();// 注册自定义的作用范围void registerScope(String scopeName, Scope scope);String[] getRegisteredScopeNames();@NullableScope getRegisteredScope(String scopeName);// 为这个bean工厂设置{ApplicationStartup} 用来记录启动步骤void setApplicationStartup(ApplicationStartup applicationStartup);ApplicationStartup getApplicationStartup();// 从一个bean工厂进行拷贝配置void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);// 注册别名void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;// 获取合并的bean的定义(RootBeanDefinition)BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;// 是否是工厂beanboolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;// 控制指定bean当前的创建状态,仅供容器内部使用void setCurrentlyInCreation(String beanName, boolean inCreation);// 判断该bean是否在创建中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);// 根据 bean 名称销毁给定的bean实例(通常是从该工厂获得的原型实例)void destroyBean(String beanName, Object beanInstance);// 销毁指定的【作用域bean】void destroyScopedBean(String beanName);// 销毁此工厂中的所有单例 Bean// 包括已注册一次性的内部bean。void destroySingletons();
ConfigurableListableBeanFactory
ConfigurableListableBeanFactory
把以上功能都整合在了一起,且拓展了核心方法 preInstantiateSingletons
.
该方法用于在实例化 Bean 之前提前实例化单例Bean的,它首先迭代所有单例 Bean 的定义并检查是否是非延迟初始化的,并且如果是工厂 Bean,则还会检查是否需要提前初始化。然后,它会触发所有适用的Bean的后期初始化回调,并执行。
二、总结
BeanFactory
:顶层接口,提供了最基础的方法,譬如:getBean、containBean
HierarchicalBeanFactory
,子接口,拓展了层次关系
ListableBeanFactory
,子接口,拓展了枚举
能力AutowireCapableBeanFactory
,子接口,拓展了自动装配
能力ConfigurableBeanFactory
,子接口,拓展了相关组件可配置化
的能力ConfigurableListableBeanFactory
,集大成者,直接实现类是 DefaultListableBeanFactory。
参考文献:
【源码】Spring —— BeanFactory 解读 1 BeanFactory 系列接口