BeanFactory的基本类体系结构(类为主):
上图可与 Spring源码分析——BeanFactory体系之接口详细分析 的图结合分析,一个以接口为主,一个以类为主
具体:
1、7层的类体系继承。
2、AbstractBeanFactory实现了最重要的ConfigurableBeanFactory接口,DefaultSingletonBeanRegistry实现了SingletonBeanRegistry单例类注册接口,SimpleAliasRegistry实现了AliasRegistry别名注册接口。
3、祖先类SimpleAliasRegistry、DefaultSingletonBeanRegistry和子孙类XmlBeanFactory、DefaultListableBeanFactory是完整的类,而中间的类FactoryBeanRegistrySupport、AbstractBeanFactory、AbstractAutowireCapableBeanFactory都是抽象类。
总结:
具体上来说,XmlBeanFactory光是父类就有6个了,加上自身,总共7层了。实际上分析接口结构就会看到,作为IOC类工厂而言,XmlBeanFactory的类体系结构实际是从祖先AbstractBeanFactory这个类开始的,因为是它实现了BeanFactory的子接口ConfigurableBeanFactory,虽然它继承自FactoryBeanRegistrySupport,但可以说这只是工厂功能的扩充,扩展了对工厂Bean以及工厂所产生的Bean的操作。
简单的别名注册器——SimpleAliasRegistry
上篇已经讲过AliasRegistry,非常简单的4个方法,体现了对别名注册的支持,而SimpleAliasRegistry就是它的简单实现。
源码:
具体:
1、1个支持高并发的ConcurrentHashMap来放置所有的别名,其中key是别名,value是真名。
2、4个方法实现了SimpleAliasRegistry。
3、3个用来辅助实现4个接口方法的方法。其中canonicalName(String name)的实现非常优雅,用来循环来回判断,把aliasMap中无对应值的key返回。
4、2个添加额外功能的方法 retrieveAliases 和 resolveAliases ,前者是找出名字对应的所有别名,后者是用一个StringValueResolver处理解析所有的别名-名称。
总结:
这是一个非常简单的别名注册器,一个简单的接口实现。不过其中包含了非常优雅的方法实现,值得一看!
默认单例注册类——DefaultSingletonBeanRegistry
源码:
具体:
1、一个静态不可变的空对象NULL_OBJECT、一个简单的日志对象。
2、本类有如下集合:
(1)、一个单例缓存集合——singletonObjects
(2)、一个单例工厂缓存集合——singletonFactories
(3)、一个早期单例对象缓存集合——earlySingletonObjects
(4)、一个注册过的单例类(单例工厂)集合——registeredSingletons
(5)、一个即将创建的单例类集合——singletonsCurrentlyInCreation
(6)、一个正在创建的单例类集合——inCreationCheckExclusions
(7)、一个被压制的异常集合——suppressedExceptions(这种设计模式实在是经典!)
(8)、一个判断所有单例类是否马上被销毁的标记——singletonsCurrentlyInDestruction
(9)、一个Disposable接口(即可以自定义回收资源的接口)实例的集合——disposableBeans
(10)、一个bean名称和bean所有包含的Bean的名称的集合——containedBeanMap
(11)、bean名称和所有依赖于Bean的名称的集合——dependentBeanMap
(12)、bean名称和bean所依赖的所有名称的集合——dependenciesForBeanMap
3、2个注册单例方法,实际是暴露在外的SingletonBeanRegistry接口的实现方法registerSingleton加锁后调用另一个addSingleton方法。
4、1个注册单例工厂的方法。单例工厂类不能和单例类同名。
5、3个获取单例类的方法。一种是从单例类集合中获取,如果获取不到,boolean控制要么返回空对象,要么返回一个单例工厂。另一种是从单例集合中获取,如果取不到,就从指定的工厂中获取。还有一种?呵,就是暴露在外的SingletonBeanRegistry接口方法呗,直接调用第一种。
6、1个添加被压制的异常集合中添加异常的方法,我觉得这个设计非常经典。但需要记录异常,却不想处理的时候,可以采用这种设计模式。
7、1个移除单例的方法、1个判断是否包含单例的方法、1个返回所有单例名数组的方法、1个返回单例总数目的方法。
8、1个设置某个Bean是否正在创建的方法、1个判断某个Bean是否正在被创建的方法、2个判断某个Bean是否即将被创建的方法(一个调用另一个,用于重写)。
9、1个单例类创建开始之前调用的方法、1个单单例类创建之后调用的方法
10、1个往Disposable实例集合注册Disposable实例的方法,这个是Bean销毁前的准备。
11、1个注册一个被包含的Bean和一个包含的Bean的名称到containedBeanMap集合的方法。这个方法设置了Bean之间的包含关系。
12、1个给指定的Bean注册一个其依赖的Bean的方法。这个方法设置了Bean自己的依赖关系。
13、1个判断是否被依赖的方法、1个返回给定Bean名称的所有依赖的数组的方法、1个返回依赖于给定Bean的所有Bean名的数组的方法。
14、1个销毁所有单例类的方法(这个方法居然完全没有注释,有没搞错!)、1个销毁某个单例的方法、1个// 销毁指定名称的Bean,且销毁依赖于它的所有Bean的方法。
15、1个返回子类单例类的互斥体的方法。这个暂且待下一篇分析子类再看。
总结:
类如其名,默认的单例注册器。这个工厂的写法实在功能丰富,为了监控到一个单例类构建过程中的方方面面,简直就是不择手段啊,居然准备了12个集合,除了一个一个被压制的异常集合,其余全是跟单例类有直接关系的。可以说,这个单例注册器监听、实现了Spring单例注册的各个过程,具体的解读分析,在上面的源代码中可以看到,读者阅读我注释过的源代码应该会很轻松。
工厂Bean注册支持——FactoryBeanRegistrySupport
废话不多说,直接看我注释的源码:
具体:
1、1个不可变的实例属性ConcurrentHashMap来存放工厂Bean生产的单例的集合:FactoryBean name --> object。
2、1个方法返回指定FactoryBean的类型的方法。
3、1个根据FactoryBean名,返回其生产的Object的方法。
4、2个从工厂Bean中取实例的方法。实际是一个方法调用另一个,取不到则返回空。
5、1个postProcessObjectFromFactoryBean的方法,留给子类重写。
6、1个取工厂Bean的方法——如果这个Object是FactoryBean类型,就转换成FactoryBean返回
7、1个重写父类的removeSingleton方法,移除单例的时候,父类的移除之外,还要移除factoryBeanObjectCache中的。
8、1个返回当前容器的安全访问上下文的方法。
总结:
这个类FactoryBeanRegistrySupport,类如其名,实现了对工厂Bean注册的支持。值得注意的是,这个类有较多类似如下的写法:
if (System.getSecurityManager() != null) {//如果当前系统存在安全管理器 return AccessController.doPrivileged(new PrivilegedAction<Class>() { public Class run() { //实际处理 } }, getAccessControlContext()); } else {//不存在安全管理器,就直接调用! //实际处理 }
这个方法的意思是,如果当前系统存在安全管理器,那么接下来的操作不做权限检查,直接调用。而如果不存在,OK,那当然是直接调用了。这是JDK层面的一个系统安全管理工具,某些情况下,可以避免系统进行安全检查。这里稍作了解即可。在学习JVM的时候可仔细了解原理。
除此之外,这里可以了解一下这个类比较重要的方法doGetObjectFromFactoryBean,是从工厂Bean中取实例的方法,源码已经给出,这里重点指出一下,不必折叠了:
//从工厂Bean中取实例,shouldPostProcess指的是是否允许提前处理 private Object doGetObjectFromFactoryBean( final FactoryBean factory, final String beanName, final boolean shouldPostProcess) throws BeanCreationException { Object object; //跟getTypeForFactoryBean的实现一样。 try { if (System.getSecurityManager() != null) {//若系统存在安全管理器 AccessControlContext acc = getAccessControlContext();//得到当前容器的安全访问上下文 try {//返回factoryBean的类型这个操作不做权限检查,直接调用 object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { return factory.getObject(); } }, acc); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else {//否则直接取 object = factory.getObject(); } } catch (FactoryBeanNotInitializedException ex) { throw new BeanCurrentlyInCreationException(beanName, ex.toString()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex); } //如果从beanFactory取不到,且这个实例即将被创建,抛出异常 if (object == null && isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } //若取不到,并非即将创建、且这个实例允许前处理 if (object != null && shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName);//这里简单返回,前处理的功能留给子类重写 } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of the FactoryBean‘s object failed", ex); } } return object; }
相信上面已经解释的很清楚了。
最重要的抽象类——AbstractBeanFactory
(PS:这个类的方法实在是多的骇人,看得我实在是头都大了。不多看到后面,发现很多方法其实也就是那么回事。源码注释了大部分,且看看咯!)
总结:方法太多了,一个个介绍很浪费时间,不具体介绍。大体介绍一下吧。这个AbstractBeanFactory继承了支持工厂Bean注册的FactoryBeanRegistrySupport,并且实现了BeanFactory重要的第三级接口——ConfigurableBeanFactory。需要具体了解这个接口,可以去看我之前的接口分析——Spring源码分析——BeanFactory体系之接口详细分析 。ConfigurableBeanFactory是一个非常复杂的接口,继承了HierarchicalBeanFactory和SingletonBeanRegistry,主要实现了工厂创建、注册Bean、单例类注册等各种功能。
AbstractBeanFactory实现了ConfigurableBeanFactory接口的绝大多数方法,实现了Bean工厂的许多重要功能,如BeanDefinition、RootBeanDefinition、原型、单例相关的各种操作。
下面列出一些主要方法实现,其他的方法说明,可具体参照上文我贴出的大部分注释过的源码。
(1)、从容器中获取bean的方法——doGetBean:
@SuppressWarnings("unchecked") protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name);//在aliasMap中取得的标准名 Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName);//首先在单例集合中取 if (sharedInstance != null && args == null) {//如果取得到,没有指定参数 if (logger.isDebugEnabled()) {//若Log允许调试 if (isSingletonCurrentlyInCreation(beanName)) {//若正准备创建,输出日志 logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName + "‘ that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘"); } } ////根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { if (isPrototypeCurrentlyInCreation(beanName)) {//如果正在被创建,就抛出异常 throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory();//取本容器的父容器 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//若存在父容器,且本容器不存在对应的Bean定义 String nameToLookup = originalBeanName(name);//取原始的Bean名 if (args != null) {//若参数列表存在 // 那么用父容器根据原始Bean名和参数列表返回 return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // 参数列表不要求,那就直接根据原始名称和要求的类型返回 return parentBeanFactory.getBean(nameToLookup, requiredType); } } //如果不需要类型检查,标记其已经被创建 if (!typeCheckOnly) { markBeanAsCreated(beanName); } //根据beanName取其根Bean定义 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn();//得到这个根定义的所有依赖 if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean);//注册这个Bean //注册一个Bean和依赖于它的Bean(后参数依赖前参数) registerDependentBean(dependsOnBean, beanName); } } // 如果Bean定义是单例,就在返回单例 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); //根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //如果是原型 else if (mbd.isPrototype()) { // It‘s a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName);//原型创建前,与当前线程绑定 prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName);//原型创建后,与当前线程解除绑定 } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else {//既不是单例又不是原型的情况 String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName);//得到范围 if (scope == null) { throw new IllegalStateException("No Scope registered for scope ‘" + scopeName + "‘"); } try {//根据范围创建实例 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args);//原型创建前,与当前线程绑定 } finally { ////原型创建后,与当前线程解除绑定 afterPrototypeCreation(beanName); } } }); //根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope ‘" + scopeName + "‘ is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } //判断要求的类型是否和Bean实例的类型正在匹配 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType);//转换类型,不抛出异常就说明类型匹配 } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean ‘" + name + "‘ to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
下面对这个方法进行简要的解释:
<1>、这个方法形参为final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly,分别表示Bean的名称、要求返回的Bean的类型、取Bean时提供的参数数组 以及 是否需要类型检查。哦
<2>、final String beanName = transformedBeanName(name); 这个方法是从aliasMap中取得对应的标准名。方法实现是,首先去掉name的 FACTORY_BEAN_PREFIX 前缀(如果是工厂Bean本身,那么Bean名有这个前缀),然后调用SimpleAliasRegistry的canonicalName方法。上篇博客已经介绍过SimpleAliasRegistry了,这里贴一下这个方法的源码:
/* * 根据name这个Key,在aliasMap中不断循环的取对应的value,如果取得到,就继续根据这个value取值,不断循环继续。 * 直到取不到,就把这个在aliasMap中无对应值的key返回。这个动作,叫规范名 */ public String canonicalName(String name) { String canonicalName = name; //规范名 // Handle aliasing... String resolvedName;//已解析名 do { resolvedName = this.aliasMap.get(canonicalName);//aliasMap中规范名对应的值赋值给已解析名 if (resolvedName != null) {//如果已解析名存在(即规范名在aliasMap中有对应的值) canonicalName = resolvedName; // 这个已解析名赋值给标准名 } } while (resolvedName != null);//不断循环,直到已解析名不存在 return canonicalName; }
<3>、首先根据标准名beanName,在单例缓存中取对应的Bean:Object sharedInstance = getSingleton(beanName);
<4>、如果取得到,且args为空,根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例:bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);然后结束整个方法。这个方法源码如下:
//根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例 protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { //如果这个Bean是工厂Bean创建的 且 这个Bean实例并不是FactoryBean实例,抛异常 if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } //如果这个Bean实例并不是FactoryBean实例 或 这个Bean是工厂Bean创建的,直接返回 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } //——————————以下都是 这个Bean实例是FactoryBean实例的情况 Object object = null; if (mbd == null) {//若根Bean定义为空,取这个BeanFactory所生产的实例 object = getCachedObjectForFactoryBean(beanName); } if (object == null) {//若取不到,那么手动取 FactoryBean<?> factory = (FactoryBean<?>) beanInstance;//把这个实例转化成一个FactoryBean // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) {//若根Bean定义为空,但是容器内有Bean定义 mbd = getMergedLocalBeanDefinition(beanName);//返回合并后的Bean定义 } boolean synthetic = (mbd != null && mbd.isSynthetic());//标记这个Bean定义是合并的 object = getObjectFromFactoryBean(factory, beanName, !synthetic);//从工厂Bean中取 } return object;
<5>、如果取不到、或 args 不为空(下面都是基于这个条件):
(如果对应的Bean正在被创建,就抛出异常)首先用父容器(如果本容器有的话)根据给出的形参取对应的Bean。
<6>、此时,判断,如果不需要类型检查,标记其已经被创建。
<7>、根据beanName取本地合并后的RootBeanDefinition(这个方法getMergedLocalBeanDefinition涉及到多层BeanDefinition相关的调用),然后检查一下。然后根据这个RootBeanDefinition,注册这个Bean和它的所有依赖。
<8>、如果这个RootBeanDefinition是单例,先根据beanName从单例缓存中取,取不到就创建一个匿名内部Bean工厂,创建一个单例,直接结束方法。
<9>、如果这个RootBeanDefinition是原型,就直接创建一个Bean返回,并在创建前把beanName与当前线程绑定,创建后解绑。
<10>、如果这个RootBeanDefinition既不是单例,又不是原型,那么根据这个RootBeanDefinition定义的范围Scope,直接创建一个scopedInstance。
<11>、若这个scopedInstance为工厂Bean,就得到它创建的实例,否则得到它自身。
<12>、对<9>或<11>中最后产生的Bean就进行一次检查,要求这个产生的Bean的类型是否和Bean实例的类型匹配,不匹配就抛出异常。
以上就是这个doGetBean方法了。其他的方法分析可参照上文的源码。
原文地址:https://www.cnblogs.com/JiangWJ/p/10800257.html