上午去缴了上次没带驾驶证的扣分罚款,最近在图书馆没事就看曾国藩家书,曾国藩说人要明强。光强没有用,你要明强。也就是说要强的有道理。曾国藩又说,作学问不能作死学问,作学问其实很重要的事就是能懂得孝悌,把家持好,能作事。能作事很重要,学问再高,不能作事,也是无用。相反即便没什么学问,写不出来,可是能作事,事事作的条理,家庭安排的和气,家族事宜可以有积极的贡献,再到更大的方面,都能作好,这才是学问的意义。看了一下,上一篇文章已是2号的了,这个月已经9号了,1/3了,但是这重头的Bean加载尚未什么大的进展,这样怎么能行,家里的事情还要办,不少事情还没弄好,这可不行呀。面试
想要人生有所突破,下一番苦工是不可能省略的。一半努力一半为所欲为,是不可能成就的。spring
“须是策励此心,勇猛奋发,拨出心肝与他去作!如两边擂起战鼓,莫问前头如何,只认卷将去!如此,方作得工夫。若半上落下,半沉半浮,济得甚事!” 朱熹 .《朱子语录》缓存
咱们继续上节的内容,这节主要是bean的加载。app
咱们从ServerMain的方法中的getBean("")做为入口来看:ide
public Object getBean(String name) throws BeansException { return this.doGetBean(name, (Class)null, (Object[])null, false); }
继续调用,都在AbstractBeanFactory中进行,下边这段就是恐怖的bean加载了。咱们能够翻到最后看下返回了Bean,固然bean是范性的,先抛开中间的过程不说,这里返回的就是实实在在的咱们须要的Bean了,彷佛一切都在这个方法里,没错全部的“恩怨”都在这里。函数
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = this.transformedBeanName(name); Object sharedInstance = this.getSingleton(beanName); Object bean; if (sharedInstance != null && args == null) { if (this.logger.isDebugEnabled()) { if (this.isSingletonCurrentlyInCreation(beanName)) { this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); } else { if (this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = this.getParentBeanFactory(); if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) { String nameToLookup = this.originalBeanName(name); if (args != null) { return parentBeanFactory.getBean(nameToLookup, args); } return parentBeanFactory.getBean(nameToLookup, requiredType); } if (!typeCheckOnly) { this.markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); String[] var11; if (dependsOn != null) { var11 = dependsOn; int var12 = dependsOn.length; for(int var13 = 0; var13 < var12; ++var13) { String dependsOnBean = var11[var13]; if (this.isDependent(beanName, dependsOnBean)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'"); } this.registerDependentBean(dependsOnBean, beanName); this.getBean(dependsOnBean); } } if (mbd.isSingleton()) { sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return AbstractBeanFactory.this.createBean(beanName, mbd, args); } catch (BeansException var2) { AbstractBeanFactory.this.destroySingleton(beanName); throw var2; } } }); bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { var11 = null; Object prototypeInstance; try { this.beforePrototypeCreation(beanName); prototypeInstance = this.createBean(beanName, mbd, args); } finally { this.afterPrototypeCreation(beanName); } bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); Scope 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 { AbstractBeanFactory.this.beforePrototypeCreation(beanName); Object var1; try { var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args); } finally { AbstractBeanFactory.this.afterPrototypeCreation(beanName); } return var1; } }); bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException var21) { 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", var21); } } } catch (BeansException var23) { this.cleanupAfterBeanCreationFailure(beanName); throw var23; } } if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return this.getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException var22) { if (this.logger.isDebugEnabled()) { this.logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } else { return bean; } }
好,下边咱们就开始这场江湖的血雨腥风。post
首先第一句就是:ui
final String beanName = this.transformedBeanName(name);
这句作的事情,好像不知道所云,由于beanName不是做为参数传进来了吗,还要再转换是什么意思,稍微想一下就知道了,咱们获取bean的时候传过来的name参数,有多是别名。this
若是是别名这里就须要转换一下了,由于咱们须要真正的名称。spa
翻看下代码:
protected String transformedBeanName(String name) { return this.canonicalName(BeanFactoryUtils.transformedBeanName(name)); }
括号里边的部分的代码以下:
public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); String beanName; for(beanName = name; beanName.startsWith("&"); beanName = beanName.substring("&".length())) { } return beanName; }
若是name是以&开头的,那么去除开头的&符号。继续:
public String canonicalName(String name) { String canonicalName = name; String resolvedName; do { resolvedName = (String)this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while(resolvedName != null); return canonicalName; }
这里很容易看出来,就是根据名称去别名map中获取有没有对应的名称。目的就是获取别名对应的真实Bean名称。
接下来这句getSingleton就涉及到伟大的又扯淡的各类面试都会问到的循环依赖问题了,其实不复杂,可是没认真研究过代码。关于循环依赖的问题,能够看下个章节。这里重点仍是建立Bean这个主题。
咱们继续上边的doCreateBean(name, requiredType, args[], typeCheckOnly)的代码。转换完名字以后,紧接的一句是getSingleton(beanName).
@Override @Nullable public Object getSingleton(String beanName) { return getSingleton(beanName, true); } /** * Return the (raw) singleton object registered under the given name. * <p>Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
这里咱们观察注释,可以了解一部分:返回已这个beanName注册的实例。而且检查已经初始化的实例,容许当前建立的实例有一个早期的引用(用来解决循环依赖问题)。
咱们深刻代码来看一下:
首先从singletonObjects.get(beanName)从缓存里获取一下,看有没有,若是有直接返回。若是没有,而且当前beanName正在建立,那么加锁后边的这部分代码:
判断beanName是否在earlySingletonObjects列表中,若是不在而且容许早期引用,那么就获取beanName对应的ObjectFactory。而后调用ObjectFactory.getObject()返回实例。并将该实例添加到earlySingletonObjects中。这里确实就是解决循环引用的核心了,解决循环依赖的核心就是这里的这个singletonFactories.get(beanName)获取singletonFactory,而后调用getOjbect返回实例。说的通俗一点儿就是可能对象尚未建立,可是可以建立这个对象的ObjectFactroy会提早放入缓存中,这样,当后续建立过程当中,须要引用一个以前尚未建立完的bean时,就会调用这里的ObjectFactory.getObject()返回一个实例对象。
这个部分咱们在下一篇专门将循环依赖的文章里详细阐述。在这里,这个getSingleton在总体流程上,最核心的是从缓存中尝试获取bean。
咱们继续看下代码,咱们用粗体标示了一个方法:getObjectForBeanInstance(scopedInstance, name, beanName, mdb)。咱们看到,后续的几种状况里,不管是singleton/prototype/仍是其余实例模式,获得bean以后,作的事情都是这个getObjectForBeanInstance方法,咱们来跟进看下:
/** 获取给定bean实例的对象,要么bean实例自己,要么当它是一个FactroyBean时,它建立出来的对象 **/ protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 若是指定的name是&开头即工厂相关的,但又不是FactoryBean类型,则抛出异常,类型验证不经过 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } } // 如今咱们有个这个bean实例,可是这个bean实例多是普通bean也多是FactoryBean,若是是FactoryBean,那么咱们使用它来获取工厂实例,若是调用者须要的是
FactoryBean自己,那么beanName参数须要带"&" if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 到这里就明确是一个FactoryBean,由于若是不是上边已经返回了 Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
1:判断是不是FactoryBean,判断依据是 beanName是不是"&"开头的。若是是&开头,则表示是获取FactoryBean自己,若是不是&开头,则是获取FactroyBean的方法返回的Bean。若是是&开头,可是自己并非FactoryBean类型,则抛出异常。
2:若是自己不是FactoryBean类型或者beanName不是以“&”开头的,那么直接返回Bean自己。
3:判断BeanDefinitions中是否存在该beanName。这里作的事情实际上是将咱们解析时候生成的GenericBeanDefinition转换成RootBeanDefinition.细节这里就不说了。
4:最后委托给getObjectFromFactoryBean(factory, beanName, !synthetic)方法类获取真正的实例。
咱们继续往下看:
/** 得到从给定的FactoryBean获取出来的对象*/ protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = doGetObjectFromFactoryBean(factory, beanName); // Only post-process and store if not put there already during getObject() call above // (e.g. because of circular reference processing triggered by custom getBean calls) Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { if (shouldPostProcess) { if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } beforeSingletonCreation(beanName); try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex); } finally { afterSingletonCreation(beanName); } } if (containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } } return object; } } else { Object object = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } return object; } }
核心其实就是这句doGetObjectFromFactoryBean(factory, beanName)。里边的if里是判断是不是单例,而里边的内容跟else的区别就是若是是单例,那么就尝试从缓存中获取,若是缓存中没有才调用到doGetObjectFactoryBean(factory, beanName)。还有里边的beforeSingletonCreation和afterSingletonCreation则都是保证建立过程当中,不会重复建立实例,是为了保证单例性。
好了,咱们仍是继续一层一层的往下看吧。
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; try { if (System.getSecurityManager() != null) { AccessControlContext acc = getAccessControlContext(); try { object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) 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); } // Do not accept a null value for a FactoryBean that's not fully // initialized yet: Many FactoryBeans just return null then. if (object == null) { if (isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } object = new NullBean(); } return object; }
终于到了最后获取对象的地方了,这里getObject()的调用为整个经过FactoryBean获取实例的解析过程画上美丽的句号。
承接上文,咱们对缓存中获取bean和FactoryBean方式获取Bean进行了阐述。对getBean("")方法进行了阐述。这一篇咱们先深刻单例的建立来详细说一下spring循环依赖问题的解决。
咱们从doGetBean方法继续,咱们主要看下singleton这一部分:
// Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
咱们继续getSingleton(beanName, singletonFactory)。
/** * 返回beanName注册过的单例对象,若是没有,那么建立并注册该beanName的实例*/ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); // 1 if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); // 2 boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); // 3 newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); // 4 } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
这里其实最核心的就是singletonFactory.getObject()。咱们梳理下步骤:
1:尝试从缓存获取beanName对应的bean
2:若是没有,调用beforeSingletonCreation(beanName),将beanName放入singletonCurrentlyInCreation列表。
3:经过调用参数传入的FactoryBean的getObject方法,获取实例化bean
4:加载完成后,处理以后的方法调用。这里作的事情跟beforeSingletonCreation正好相反,把beanName从singletonCurrentlyInCreation中删除
5:缓存生成的object。并删除生成过程当中的相关状态。
/** * Add the given singleton object to the singleton cache of this factory. * <p>To be called for eager registration of singletons. * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); // 放入缓存 this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
6:返回bean,这个bean就是上边getSingleton(beanName, singletonFactory)的这个参数,在doGetBean中定义的方法。
sharedInstance = getSingleton(beanName, () -> { // 这里是jdk8引入的函数是写法,这里其实就是ObjectFactroy的一个匿名类实现 try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } });
接下来就是建立bean的代码了。
咱们来详细看下这个createBean(beanName, mdb, args)
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolv1ed at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
1:根据mdb获取beanName对应的class。
2:对override属性进行处理
3:应用初始化前的处理器
4:建立bean
咱们来详细看下override 的处理
/** * Validate and prepare the method overrides defined for this bean. * Checks for existence of a method with the specified name. * @throws BeanDefinitionValidationException in case of validation failure */ public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists. if (hasMethodOverrides()) { Set<MethodOverride> overrides = getMethodOverrides().getOverrides(); synchronized (overrides) { for (MethodOverride mo : overrides) { prepareMethodOverride(mo); } } } } /** * Validate and prepare the given method override. * Checks for existence of a method with the specified name, * marking it as not overloaded if none found. * @param mo the MethodOverride object to validate * @throws BeanDefinitionValidationException in case of validation failure */ protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0) { throw new BeanDefinitionValidationException( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); } else if (count == 1) { // Mark override as not overloaded, to avoid the overhead of arg type checking. mo.setOverloaded(false); } }
这里咱们要理解下lookup-method和override-method的问题。这两个配置咱们在解析xml的时候说过但没有太详细介绍,这两个的做用lookup-method。(这里不太明白还,暂时放这里,后续bean生成的时候看下到底代码如何实现的,再过来看)