少年辛苦终身事,莫向光阴惰寸功。这篇文章主要讲述Spring源码分析带你正视一下Spring祖容器之BeanFactory的原理与功能分析相关的知识,希望能为你提供帮助。
BeanFactory
BeanFactory类的介绍
BeanFactory里注释进行详细分析.
BeanFactory的介绍说明
- 访问一个Spring bean容器的根接口。这是一个bean容器的基本客户端视图;
进一步的接口,如 ListableBeanFactory 和org.springframework.beans.factory.config.ConfigurableBeanFactory}可用于特殊目的。
- 【Spring源码分析带你正视一下Spring祖容器之BeanFactory的原理与功能分析】此接口由持有一些bean定义的对象来实现,每个bean由String字符串唯一标识。根据bean定义,工厂将返回一个独立对象实例(原型设计模式),或者一个单个共享实例(Singleton设计模式的优雅代替实现,其中该实例是一个factory范围内的单例)。
- 实例的哪种类型将被返回依赖于bean工厂配置:即使API是一样的。从Spring2.0开始,作用域扩展到根据具体的应用上下文,如web环境的request,session。
- 这种方案的关键是,BeanFactory的是应用程序组件注册的中心,同时集中应用程序组件的配置(程序模块不再需要读取诸如properties的配置文件)。这种设计的更多好处讨论详见的< J2EE设计开发编程指南> 第4和第11章.
- 相比诸如 BeanFactory 中查找的pull配置方式,通过setters或者构造方法,依赖注入的方式配置应用对象更好,Spring的依赖注入功能就是通过实现BeanFactory和其子接口实现的.
- 通常,一个BeanFactory会从配置源(如XML文件)中加载bean对象模型,并使用{@code org.springframework.beans}包解析bean。然而,实现可以简单地返回java代码直接新建的Java对象。这里没有限制bean 定义文件的格式:LDAP,RDBMS,XML.实现类欢迎支持应用而非bean(依赖注入)
- 对比{@ListableBeanFactory}中的方法,如果这是一个{@link HierarchicalBeanFactory},这个接口的全部实现都会查找父工厂,如果在这个工厂实例找不到bean,去直接父工厂查找。factory实例中的bean会覆盖父factory实例中的同名bean。
- 实现类应该尽量支持标准bean的生命周期接口.全套的初始化方法。
public interface BeanFactory {/**
* 用于区分是否直接获取FactoryBean实例.
* bean以&
开头表示获取FactoryBean实例.否则获取created的实例.For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &
myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
String FACTORY_BEAN_PREFIX = "&
";
/**
* 返回一个原型或者单例实例.
* 抢单例,原型设计模式的饭碗
* 可以根据别名查找,也可以去父容器实例查找
*/
Object getBean(String name) throws BeansException;
/**
* 加个类型
*/
<
T>
T getBean(String name, Class<
T>
requiredType) throws BeansException;
/**
* 根据类型获取bean实例.可以是接口或子类,但不能是{@code null}.
* {@link ListableBeanFactory}也可以使用类型转化为name进行查找.更多bean集合的操作可以看
* ListableBeanFactory和BeanFactoryUtils
*/
<
T>
T getBean(Class<
T>
requiredType) throws BeansException;
/**
* 多了构造方法,工厂方法的参数
*/
Object getBean(String name, Object... args) throws BeansException;
/**
* 判断是否包含bean(包括别名,父容器)
* 陷阱出现:这边不管类是否抽象类,懒加载,是否在容器范围内,只要符合都返回true,所以这边true,不一定能从getBean获取实例
*/
boolean containsBean(String name);
/**
* 是否单例
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 是否原型
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 是否有跟name匹配类型的bean
*/
boolean isTypeMatch(String name, Class<
?>
targetType) throws NoSuchBeanDefinitionException;
/**
* 根据bean name获取类型
*/
Class<
?>
getType(String name) throws NoSuchBeanDefinitionException;
/**
* 获取别名
*/
String[] getAliases(String name);
}
- Object getBean(String name) throws BeansException;
可以用别名查找哦
- <
T>
T getBean(String name, Class<
T>
requiredType) throws BeansException;
- <
T>
T getBean(Class<
T>
requiredType) throws BeansException;
这边的类型可以是接口或者子类,但不能是null
- Object getBean(String name, Object... args) throws BeansException;
- 判断是否包含bean.陷阱出现:这边不管类是否抽象类,懒加载,是否在容器范围内,只要符合都返回true,所以这边true,不一定能从getBean获取实例
- boolean containsBean(String name);
- 单例,原型,bean类型的判断
- boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
- boolean isTypeMatch(String name, Class< ?> targetType) throws
NoSuchBeanDefinitionException;
- 获取bean 的类型,别名
- Class< ?> getType(String name) throws NoSuchBeanDefinitionException;
- String[] getAliases(String name);
- AutowireCapableBeanFactory 添加集成其他框架功能,如果集成WebWork则可以使用Spring对Actions等进行管理.
-
- HierarchicalBeanFactory:提供父容器的访问功能
-
- ConfigurableBeanFactory:如名,提供factory的配置功能。
-
-
- ConfigurableListableBeanFactory:集大成者,提供解析,修改bean定义,并与初始化单例.
-
- ListableBeanFactory 提供容器内bean实例的枚举功能,这边不会考虑父容器内的实例.
文章图片
AutowireCapableBeanFactory在BeanFactory基础上实现对已存在实例的管理.
- 可以使用这个接口集成其它框架,捆绑并填充并不由Spring管理生命周期并已存在的实例.像集成其他框架机制。
- 一般应用开发者不会使用这个接口,所以像ApplicationContext这样的外观实现类不会实现这个接口,如果真手痒痒可以通过ApplicationContext的getAutowireCapableBeanFactory接口获取。
- 不注入:AUTOWIRE_NO
- 使用bean name策略装配:AUTOWIRE_BY_NAME
- 使用类型装配策略:AUTOWIRE_BY_TYPE
- 使用构造器装配策略:AUTOWIRE_CONSTRUCTOR
- 自动装配策略:AUTOWIRE_AUTODETECT
创建和填充外部bean实例的典型方法
<
T>
T createBean(Class<
T>
beanClass) throws BeansException;
// 使用autowireBeanProperties装配属性
void autowireBean(Object existingBean) throws BeansException;
// 自动装配属性,填充属性值,使用诸如setBeanName,setBeanFactory这样的工厂回调填充属性,最好还要调用post processor
Object configureBean(Object existingBean, String beanName) throws BeansException;
Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
在bean的生命周期进行细粒度控制的专门方法
Object createBean(Class<
?>
beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
// 会执行bean完整的初始化,包括BeanPostProcessors和initializeBeanObject autowire(Class<
?>
beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException;
void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
Object initializeBean(Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<
String>
autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
HierarchicalBeanFactory获取父容器 bean factory判断当前容器是否保护beanListableBeanFactory获取bean时,Spring 鼓励使用这个接口定义的api,其他的4个接口都是不鼓励使用的.
提供容器中bean迭代的功能,不再需要一个个bean地查找,比如可以一次获取全部的bean,根据类型获取bean.在看SpringMVC时,扫描包路径下的具体实现策略就是使用的这种方式(那边使用的是BeanFactoryUtils封装的api).
如果同时实现了HierarchicalBeanFactory,返回值不会考虑父类BeanFactory,只考虑当前factory定义的类.当然也可以使用BeanFactoryUtils辅助类来查找祖先工厂中的类.
- 这个接口中的方法只会考虑本factory定义的bean.
- 这些方法会忽略ConfigurableBeanFactory的registerSingleton注册的单例bean(getBeanNamesOfType和getBeansOfType是例外,一样会考虑手动注册的单例).
- 当然BeanFactory的getBean一样可以透明访问这些特殊bean.当然在典型情况下,所有的bean都是由external bean定义,所以应用不需要顾虑这些差别.
- boolean containsBeanDefinition(String beanName);
//是否包含bean
- int getBeanDefinitionCount();
// 当前factory中定义的bean数量
- String[] getBeanDefinitionNames(); // 获取当前工厂中定义的所有bean 的name
这边的方法仅检查顶级bean.它不会检查嵌套的bean.FactoryBean创建的bean会匹配为FactoryBean而不是原始类型.
一样不会考虑父factory中的bean,非要用可以通过BeanFactoryUtils中的beanNamesForTypeIncludingAncestors.
这个版本的getBeanNamesForType会匹配所有类型的bean,包括单例,原型,FactoryBean.返回的bean names会根据backend 配置的进行排序.
- String[] getBeanNamesForType(Class<
?>
type);
// 获取给定类型的bean names(包括子类),通过bean 定义或者FactoryBean的getObjectType判断.
- String[] getBeanNamesForType(Class<
?>
type, boolean includeNonSingletons, boolean allowEagerInit);
- <
T>
Map<
String, T>
getBeansOfType(Class<
T>
type) throws BeansException;
// 如果保护懒加载的类,FactoryBean初始化的类和工厂方法初始化的类会被初始化.就是说执行这个方法会执行对应的初始化.
- < T> Map< String, T> getBeansOfType(Class< T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
- Map< String, Object> getBeansWithAnnotation(Class< ? extends Annotation> annotationType) throws BeansException;
- < A extends Annotation> A findAnnotationOnBean(String beanName, Class< A> annotationType);
推荐阅读
- SpringBoot技术专题「权限校验专区」Shiro整合JWT授权和认证实现
- 「绝密档案」“爆料”完整秒杀架构的设计到技术关键点的“八卦追踪”
- Alibaba工具型技术系列「EasyExcel技术专题」实战项目中常用的Excel操作指南
- SpringBoot技术专题「开发实战系列」动态化Quartz任务调度机制+实时推送任务数据到前
- Spring功能介绍加载时织入机制的Aspectj和LoadTimeWeaving技术
- C语言进阶——数据的存储
- u盘安装win7系统详细图文详细教程图解
- 装机高手教你怎样用u盘安装win7系统
- U打开u盘制作工具最新推荐