Spring IOC-BeanFactory的继承体系结构

本文主要介绍BeanFactory以及它的各种继承层级的接口、抽象类及实现类,因为内容很多,所以这里不介绍ApplicationContext继承体系下的类(虽然ApplicationContext本质上也是BeanFactory,但是毕竟这这是我们平时接触最多的两种类别,所以分开说)。
关于ApplicationContext继承体系结构在《Spring IOC-ApplicationContext的继承体系结构》一文分享说明。
BeanFactory其实就是Spring的IOC容器,当然了Spring为我们准备了许多种IOC容器来使用,这样可以方便我们从不同的层面,不同的资源位置,不同的形式的定义信息来建立我们需要的IoC容器。
在鄙人博客的不同的博文中其实都提到了Spring的一个设计理念,就是接口-抽象类-实现类的体系结构,这里多说几句为什么这么设计,熟悉设计模式的人都知道,这样的目的是为了提高软件的可维护性、可扩展性、强复用性。说的文雅一点就是使代码满足“对修改关闭、对扩展开放”、“里氏代换”原则 、“依赖倒转”原则、“接口隔离”原则、“合成\聚合复用”原则。如果项了解这几个原则可以百度下,这里不详细介绍。
废话不多说,直接上代码来看下BeanFactory的继承道理多屌。
先贴张图,大家大致看下知道下面介绍的类大概在继承体系的哪个位置。
在这里插入图片描述
首先看BeanFactory接口中定义的方法:

public interface BeanFactory {//这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象String FACTORY_BEAN_PREFIX = "&";//这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。 Object getBean(String name) throws BeansException;//这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。<T> T getBean(String name, Class<T> requiredType);<T> T getBean(Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;//这里提供对bean的检索,看看是否在IOC容器有这个名字的beanboolean containsBean(String name);//这里根据bean名字得到bean实例,并同时判断这个bean是不是单件 boolean isSingleton(String name) throws NoSuchBeanDefinitionException;//这里根据bean名字得到bean实例,并同时判断这个bean是不是原型 boolean isPrototype(String name) throws NoSuchBeanDefinitionException;//这里对得到bean实例的Class类型  Class<?> getType(String name) throws NoSuchBeanDefinitionException;//这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来  String[] getAliases(String name);

然后在看BeanFactory 的直接继承接口(二级接口),有HierarchicalBeanFactory、AutowireCapableBeanFactory和ListableBeanFactory看这三个类代码:

HierarchicalBeanFactory
作用:是为了实现bean工厂的层级关系提供支持,其中声明两个方法:

//得到父工厂
BeanFactory getParentBeanFactory();
//在本地工厂中有没有给定名称的bean,不包括继承的工厂
boolean containsLocalBean(String name);

AutowireCapableBeanFactory
作用:提供自动装配bean能力的功能支持,声明方法如下:(这个接口中所有声明的方法都是在默认的实现实在AbstractAutowireCapableBeanFactory类中默认实现)

//用个给定的class类型制造一个完整的bean
<T> T createBean(Class<T> beanClass) throws BeansException;
//bean初始化完成之后执行回调函数和后处理器,
void autowireBean(Object existingBean) throws BeansException;
// 自动注入和设置bean的属性、执行factory回调函数比如setBeanName和setBeanFactory和执行bean的所有的后处理器
Object configureBean(Object existingBean, String beanName) throws BeansException;
//调用bean的init方法,这个方法是客户配置的,在bean实例化之后调用
Object initializeBean(Object existingBean, String beanName) throws BeansException;
//初始化完成之后应用后处理器
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
//应用前处理器
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName);

ListableBeanFactory
作用:可以枚举所有的bean实例,是为了使客户端访问工厂中的bean而设计的,主要方法(这些方法顾名思义,所有的方法实现在StaticListableBeanFactory、AbstractApplicationContext和DefaultListableBeanFactory中):

//是否含有给定的名称的bean
boolean containsBeanDefinition(String beanName);
int getBeanDefinitionCount();
//得到工厂所有的bean的名称数组
String[] getBeanDefinitionNames();
String[] getBeanNamesForType(Class<?> type);
//根据给定的类型得到和相应的策略得到所有的bean名称数组
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
//根据给定过的类型得到所有该类型的bean,返回的结果是一个Map<bean名称,bean对象>的形式
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
//得到给定名称的bean上的给定注解类型的注解对象
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);

下面我们介绍BeanFactory 的三级接口,看继承关系图知道是ConfigurableBeanFactory和ConfigurableListableBeanFactory。

ConfigurableBeanFactory
作用: 实现可配置的bean的环境功能,这个接口继承自HierarchicalBeanFactory所以支持层级关系的工厂,和SingletonBeanRegistry所以肯定支持单例工厂行为,看主要方法代码(在AbstractBeanFactory类中默认实现):

void setConversionService(ConversionService conversionService);
void setTypeConverter(TypeConverter typeConverter);
//支持自定义bean的作用范围,可以理解为单例和多例之外的
void registerScope(String scopeName, Scope scope);
//归并的将给定的name的bean的定义
BeanDefinition getMergedBeanDefinition(String beanName);
//添加处理器
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
//下面是3个destory方法
void destroyBean(String beanName, Object beanInstance);
void destroyScopedBean(String beanName);
//只能销毁所有单例的bean,因为多例的是不归Spring控制的,是由客户端控制的
void destroySingletons();

ConfigurableListableBeanFactory
作用:提供可配置的、可访问的功能,接口中的方法在在DefaultListableBeanFactory默认实现默认实现。

public interface ConfigurableListableBeanFactoryextends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {//冻住之后bean定义就不能在被修改和进行任何的后处理器规定的操作void freezeConfiguration();//确保所有的单例bean都实例化void preInstantiateSingletons() throws BeansException;//BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;//判断当前的bean是不是作为其它bean的依赖注入的boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor);

上面是接口的继承体系和说明,下面来介绍接口下抽象类的代码,在上面的介绍中我们知道就两个抽象类AbstractAutowireCapableBeanFactory和AbstractBeanFactory,先看继承关系:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactoryimplements AutowireCapableBeanFactory {
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

可以知道AbstractAutowireCapableBeanFactory 是AbstractBeanFactory 类的子类。通过上面的接口和抽象类的介绍我们将研究的重点转到转到这两个抽象类中。
这里我们主要看bean工厂是怎么将xml中的定义信息转换为互相依赖的bean定义或者初始化为实体对象。
先看在继承体系偏上的类AbstractBeanFactory ,这个类最重要的是对BeanFactory中getBean()的实现,直接看实现的代码:

………………
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {return doGetBean(name, requiredType, args, false);
}

在看doGetBean()方法代码:

………………
//首先从单例工厂得到有没有
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//不是但单例的
else {//看是不是在父BeanFactory ,因为实现了HierarchicalBeanFactory接口BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {return parentBeanFactory.getBean(nameToLookup, requiredType);}
……………………if (mbd.isSingleton()) {//单例的//用回调的形式建造bean并且放入单例工厂sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {public Object getObject() throws BeansException {try {return createBean(beanName, mbd, args);}……………………//多例的else if (mbd.isPrototype()) {Object prototypeInstance = null;beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);………………else {//没有明确是单例的还是不是,有自己的作用域scopeString scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {public Object getObject() throws BeansException {				return createBean(beanName, mbd, args);……………………

可以上面是分为三种情况得到bean的,单例的、多例的、Scope的。但是所有的情况最终都定位到一个方法——createBean(beanName, mbd, args),这个方法在AbstractBeanFactory 是抽象的protected abstract Object createBean(,很明显,只能在子类中实现,自然就要看AbstractAutowireCapableBeanFactory 中的建造bean的createBean()代码:

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {………………//如果没有找到这个name的class类型是会抛出异常的resolveBeanClass(mbd, beanName);//判断在xml中定义的overrides方法存在mbd.prepareMethodOverrides();………………//用bean的前处理器去实例化Object bean = resolveBeforeInstantiation(beanName, mbd);………………Object beanInstance = doCreateBean(beanName, mbd, args);………………

好的,代码定位到**doCreateBean(beanName, mbd, args)**方法:

//逐渐的构造一个bean,分别用factory method, and autowiring a constructor.去构造,这些都是在xml中配置的。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {………………instanceWrapper = createBeanInstance(beanName, mbd, args);………………//构造bean并且注入依赖所有bean的属性值Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {//调用配置的init方法exposedObject = initializeBean(beanName,     exposedObject, mbd);} }

代码定位到createBeanInstance(beanName, mbd, args)

//用 factory method, constructor autowiring, or simple instantiation.三种方法去实例化一个bean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {………………//用getFactoryMethodName去实例化一个if (mbd.getFactoryMethodName() != null)  {return instantiateUsingFactoryMethod(beanName, mbd, args);}………………//用构造函数if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {//用默认的构造函数得到return instantiateBean(beanName, mbd);}………………
}

再定位代码到populateBean(beanName, mbd, instanceWrapper):

//主要是bean中的成员变量的初始化和注入,《依赖的注入》
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {……………………if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||     mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs);              // Add property values based on autowire by name if applicable.             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs);                              }                                                                           // Add property values based on autowire by type if applicable.             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs);                              }                                                                           pvs = newPvs;                                                               
}                                                                               ……………………//将属性的引用和具体的对象结合起来,用到了java的反射机制applyPropertyValues(beanName, mbd, bw, pvs);
}

最后是applyPropertyValues(beanName, mbd, bw, pvs)

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {try {//调用BeanWrapper类的方法bw.setPropertyValues(new MutablePropertyValues(deepCopy));}

这里补充一下BeanWrapperImpl类中设置属性依赖的代码实现:

………………
//如果有key属性配置,证明是array  list  或者map
if (tokens.keys != null) {if (propValue.getClass().isArray()) {else if (propValue instanceof List) {else if (propValue instanceof Map) {
}
//普通的属性设置
else{………………writeMethod.setAccessible(true);writeMethod.invoke(object, value);
}
………………

至此bean的如何初始化和如何进行依赖注入就已经研究代码完毕。
下面也是最后我们看一下这个继承体系中具体类XmlBeanFactory、DefaultListableBeanFactory的实现代码:
XmlBeanFactory

//这个类的实现很简单,只是委托XmlBeanDefinitionReader进行xml的读取和配置信息的加载
public class XmlBeanFactory extends DefaultListableBeanFactory {private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);// 构造的时候就进行xml文件的解析public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {super(parentBeanFactory);this.reader.loadBeanDefinitions(resource);}
}

关于XmlBeanFactory加载xml,会在Spring IOC-XmlBeanFactory如何加载xml及如何存储转换后的信息一文介绍。

DefaultListableBeanFactory
是XmlBeanFactory的父类,也就是而你看下文章最前面的继承图,你会发现DefaultListableBeanFactory拥有这个继承体系中的所有功能。
那么除了继承父类的功能方法外,它独特的功能在于对ConfigurableListableBeanFactory和ListableBeanFactory接口的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249550.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PHP】xampp配置多个监听端口和不同的网站目录(转)

转自&#xff1a;https://blog.csdn.net/cc1314_/article/details/75646344 windows下使用xampp配置多个监听端口和不同的网站目录 一&#xff1a;配置Apache文件httpd.conf打开Apache的配置文件httpd.conf&#xff0c;可以通过点击xampp的Apache的config下的Apache(httpd.conf…

Java消息中间件

1.概述 中间件 非底层操作系统软件&#xff0c;非业务应用软件&#xff0c;不是直接给最终用户使用的&#xff0c;不能直接给客户带来价值的软件统称为中间件。 消息中间件 管制关注于数据的发送和接收&#xff0c;利用高效可靠的异步消息传递机制集成分布式系统。 优点 ① 解…

form 源码刨析

def clean_name(self) value self.cleaned_data.get(name) if "金-瓶-梅" not in value: raise ValidationError("不符合要求") return value 重写clean方法 转载于:https://www.cnblogs.com/wuheng-123/p/9623289.html

Activemq源码、编译、导入idea、源码调试总结

1、在本地下载源码 在GitHub官网搜activemq&#xff0c;找到排名第一的&#xff0c;并打开&#xff0c;如图所示&#xff0c;拷贝url地址。 activemq托管地址&#xff1a;https://github.com/apache/activemq.git 切换到git bash下&#xff0c;输入命令&#xff1a; mkdir a…

activiti 视图

1. application.properties增加如下配置 spring.activiti.database-schema-updatefalsespring.activiti.db-history-usedfalsespring.activiti.db-identity-usedfalse 2. 视图sql -- 修改表名称 ALTER TABLE act_id_user RENAME act_id_user_bak1; ALTER TABLE act_id_group RE…

ActiveMQ源码解析 建立连接

作为一个消息中间件&#xff0c;有客户端和服务端两部分代码&#xff0c;这次的源码解析系列主要从客户端的代码入手&#xff0c;分成建立连接、消息发送、消息消费三个部分。趁着我昨天弄明白了源码编译的兴奋劲头还没过去&#xff0c;今天研究一下建立连接的部分。 如果读起…

原生Js_实现广告弹窗

广告样式当页面加载后5s刷新在右下角 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>Gary图片轮播</title><style type"text/css">#ad{width:300px;height: 300px;background-color:antiquewhite…

springcloud注册中心eureka

1、前提 springcloud的注册中心是以springboot为基础搭建起来的。 开发工具&#xff1a;IDEA 项目管理工具&#xff1a;maven 2、搭建步骤 创建一个web项目&#xff08;建议使用IDEA工具构建项目&#xff09;修改pom文件 <dependency><groupId>org.springframework…

Nancy in .Net Core学习笔记 - 视图引擎

前文中我们介绍了Nancy中的路由&#xff0c;这一篇我们来介绍一下Nancy中的视图引擎。 Nancy中如何返回一个视图(View) 在ASP.NET Mvc中&#xff0c;我们使用ViewResult类来返回一个视图。Nancy中也提供了类似的功能, 在NancyModule类中&#xff0c;Nancy提供了一个ViewRendere…

设计模式之组合模式(Composite 模式)

引入composite模式 在计算机文件系统中&#xff0c;有文件夹的概念&#xff0c;文件夹里面既可以放入文件也可以放入文件夹&#xff0c;但是文件中却不能放入任何东西。文件夹和文件构成了一种递归结构和容器结构。 虽然文件夹和文件是不同的对象&#xff0c;但是他们都可以被放…

HierarchicalBeanFactory接口

HierarchicalBeanFactory 提供父容器的访问功能.至于父容器的设置,需要找ConfigurableBeanFactory的setParentBeanFactory(接口把设置跟获取给拆开了!). HierarchicalBeanFactory源码具体&#xff1a; 1、第一个方法返回本Bean工厂的父工厂。这个方法实现了工厂的分层。 2、第…

C++: C++函数声明的时候后面加const

C: C函数声明的时候后面加const 转自&#xff1a;http://blog.csdn.net/zhangss415/article/details/7998123 非静态成员函数后面加const&#xff08;加到非成员函数或静态成员后面会产生编译错误&#xff09;&#xff0c;表示成员函数隐含传入的this指针为const指针&#xff0…

【计蒜客习题】消除字符串

问题描述 蒜头君喜欢中心对称的字符串&#xff0c;即回文字符串。现在蒜头君手里有一个字符串 SS&#xff0c;蒜头君每次都会进行这样的操作&#xff1a;从 SS 中挑选一个回文的子序列&#xff0c;将其从字符串 SS 中去除&#xff0c;剩下的字符重组成新的字符串 SS。 蒜头君想…

Training a classifier

你已经学习了如何定义神经网络&#xff0c;计算损失和执行网络权重的更新。 现在你或许在思考。 What about data? 通常当你需要处理图像&#xff0c;文本&#xff0c;音频&#xff0c;视频数据&#xff0c;你能够使用标准的python包将数据加载进numpy数组。之后你能够转换这些…

ListableBeanFactory接口

ListableBeanFactory获取bean时,Spring 鼓励使用这个接口定义的api. 还有个Beanfactory方便使用.其他的4个接口都是不鼓励使用的. 提供容器中bean迭代的功能,不再需要一个个bean地查找.比如可以一次获取全部的bean(太暴力了),根据类型获取bean.在看SpringMVC时,扫描包路径下的…

面向对象之三大特性:继承,封装,多态

python面向对象的三大特性&#xff1a;继承&#xff0c;封装&#xff0c;多态。 1. 封装: 把很多数据封装到⼀个对象中. 把固定功能的代码封装到⼀个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了⼀个很⽜B的函数. 那这个也可以被称为…

configurablebeanfactory

ConfigurableBeanFactory定义BeanFactory的配置.ConfigurableBeanFactory中定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory,bean如何销毁. ConfigurableBeanFactory同时继承了Hi…

外观模式

一、什么是外观模式   有些人可能炒过股票&#xff0c;但其实大部分人都不太懂&#xff0c;这种没有足够了解证券知识的情况下做股票是很容易亏钱的&#xff0c;刚开始炒股肯定都会想&#xff0c;如果有个懂行的帮帮手就好&#xff0c;其实基金就是个好帮手&#xff0c;支付宝…

OC内存管理

OC内存管理 一、基本原理 &#xff08;一&#xff09;为什么要进行内存管理。 由于移动设备的内存极其有限&#xff0c;所以每个APP所占的内存也是有限制的&#xff0c;当app所占用的内存较多时&#xff0c;系统就会发出内存警告&#xff0c;这时需要回收一些不需要再继续使用的…

面试题集锦

1. L1范式和L2范式的区别 (1) L1范式是对应参数向量绝对值之和 (2) L1范式具有稀疏性 (3) L1范式可以用来作为特征选择&#xff0c;并且可解释性较强&#xff08;这里的原理是在实际Loss function 中都需要求最小值&#xff0c;根据L1的定义可知L1最小值只有0&#xff0c;故可以…