spring最为基础也是极为重要的一个元素单位便是bean,bean由开发者编写的普通java类经过spring按照开发者指定的规则生成而来,作为pojo的替代对象进行使用,之前的学习中已经知道spring通过doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)方法来创建bean实例,简单回顾一下方法里三个参数的作用:
-
beanName:bean的名称,也是bean的标识
-
RootBeanDefinition mbd:一个用来描述bean的对象
-
Object[] args:创建构造函数和工程方法的时候用到的一些参数
为了写出更加出彩、难以发现的bug还需要从源码开始学习。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {//初始化这个bean的包装,在bean创建之后会由这个对象来进行包装,对象内部会包含bean的实例和BeanDefinition(用来描述bean的对象)以及一个属性编辑器BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {//如果这个bean是单例的,就尝试着从缓存里面获取bean包装对象instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {//这里就是创建bean对象的地方,万物起始之处instanceWrapper = createBeanInstance(beanName, mbd, args);}//获取bean对象final Object bean = instanceWrapper.getWrappedInstance();//获取bean对象的类型Class<?> beanType = instanceWrapper.getWrappedClass();//NullBean的意思是内部空的beanif (beanType != NullBean.class) {//在描述文件中赋值上bean的类型mbd.resolvedTargetType = beanType;}//获取后处理的锁synchronized (mbd.postProcessingLock) {//是否已经处理过后处理器if (!mbd.postProcessed) {try {//执行合并bean定义的后处理器applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}//修改状态,已经执行过后处理器了,不需要再重复劳动mbd.postProcessed = true;}}//判断spring是否应该过早的暴露的bean对象,用来提供对循环依赖的支持。boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}//注册到单例工程中,getEarlyBeanReference这个方法会将aop动态织入bean中,如果没有aop就直接返回beanaddSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}Object exposedObject = bean;try {//填充bean的属性populateBean(beanName, mbd, instanceWrapper);//初始化beanexposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}//判断是否过早的暴露出去了,就是之前放入缓存的地方if (earlySingletonExposure) {//从singletonFactories中获取一下Object earlySingletonReference = getSingleton(beanName, false);//如果获取到了实例,if (earlySingletonReference != null) {//并且这个实例和初始化之后的bean对象是同一个,就说不是一个代理的bean对象if (exposedObject == bean) {//把缓存中的bean赋值给exposedObjectexposedObject = earlySingletonReference;}//检查依赖这个bean的bean是否都已经初始化好了else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {//获取依赖当前bean的beannameString[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {//检查这些需要依赖的bean,删除掉那些用于类型检测的bean,如果不是的加入到“actualDependentBeans”缓存中if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}//如果缓存不是空的就抛出异常if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}try {//根据配置的scopse属性,对bean进行注册,如果配置了destroy-method,也需要在这里注册,方便销毁bean的时候调用registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}//返回这个beanreturn exposedObject;
}
抛开那些烦人的异常处理和日志,回头整理一下这个方法的主要思路:
-
如果是单例的bean就先清除掉缓存
-
实例bean,将beanDefinition(bean的描述对象)转化成beanWrapper(bean的包装对象)
-
执行MergedBeanDefinitionPostProcessor的处理,主要作用就是对@Autowired和@Value注解做预处理。
-
解决循环依赖的问题
-
对bean的属性进行填充
-
检查是否发生循环依赖问题
-
注册bean
-
返回bean
方法虽然很长,但是思路清晰,过程简单,当我们了解了循环依赖和spring的解决之道后,这个方法看起来就会很轻松,也能专注于最为重要的一步,就是第二步中的createBeanInstance()方法。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {//解析获得bean的class对象Class<?> beanClass = resolveBeanClass(mbd, beanName);//如果这个beanclass是空的,或者修饰符不是public,或者没有权限访问构造函数和方法,就抛出异常if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}//初始化supplier,这个对象可以把bean包装成beanWrapperSupplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}//如果工厂方法不为空,就根据工厂方法初始化策略if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}//是否曾经创建过这个beanboolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {//resolvedConstructorOrFactoryMethod不为空的话,曾经就创建过这个beanif (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;//constructorArgumentsResolved为true说明之前采用的是构造函数自动注入的方式autowireNecessary = mbd.constructorArgumentsResolved;}}}//如果曾经解析过,就使用之前的解析好的构造方法if (resolved) {if (autowireNecessary) {//使用构造函数自动注入return autowireConstructor(beanName, mbd, null, null);}else {//使用默认的构造函数return instantiateBean(beanName, mbd);}}// 走到这里说明是第一次创建bean,获取构造函数Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {//构造函数的方式进行加载return autowireConstructor(beanName, mbd, ctors, args);}//如果设置了指定的构造函数,就是用这个构造函数进行加载ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// 直接初始化beanreturn instantiateBean(beanName, mbd);
}
spring实例化bean的细节还是相当复杂的,spring将逻辑提取到createBeanInstance()方法中,将具体实现封装到autowireConstructor()和instantiateBean()的方法中。
-
查看BeanDefinition中指定了Supplier或者指定了工厂方法,就直接从这里跳过去,并且返回结果。
-
解析构造函数,并通过构造函数进行实例化。一个类可能有多个构造函数,每个构造函数的参数不同,spring根据参数数量和类型判断最终使用哪个构造函数进行实例化。但是判断的过程是个比较消耗性能的步骤,spring采用了一个缓存的机制,减少重复的解析。
autowireConstructor()和instantiateBean()两个方法的冗长又极为复杂,让人难以理解又昏昏欲睡,所以我们还是留到下一次再讲,我先睡一会(?3[▓▓] 果然看源码是最好的安眠药。。。。