AbstractBeanFactory.getBean的流程,有点像老外点餐,不信我们往下看。spring
AbstractBeanFactory中有getBean的通用逻辑缓存
//AbstractBeanFactory 中getBean方法第源码 @Override public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false); }
核心逻辑在:doGetBean中。app
getBean流程 | 老外点餐 |
获取BeanName,BeanFactory去掉&,根据别名找到对应的BeanName | 饭店老板翻译老外说的 |
尝试从缓存中获取单例,若是存在就返回 | 餐馆老板看看有没有作好的,有就端出来给老外 |
检查是不是原型类型Bean在建立中,若是是,假设存在循环引用,抛出异常 | 老板看看是否是正在作,若是说是就无论了 |
找到定义bean对应的BeanFactory | 老板找到张大厨 |
将多个GernericBeanDefinition合并为ide RootBeanDefinition,若是Bean有父Bean,时会合并父类的相关属性ui |
老板将客人的要求汇总给,供厨师使用 |
保证bean的依赖先初始化,对DependOn注解的支持 | 完成作这道菜的必须工做,例如洗菜 |
按不一样做用域建立Bean | 厨师作菜 |
若是须要进行类型装换 |
玩笑事后让咱们看点实在的。this
/** * 得到一个实例,能够是共享(原型的),独立(单例的),指定的bean * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use when creating a bean instance * using explicit arguments * (only applied when creating a new instance as opposed to retrieving an existing one) * args (仅在建立一个新实例时使用,而不是获取一个已经存在的bean) * @param typeCheckOnly whether the instance is obtained for a type check,not for actual use * 是否仅仅是类型检查 * @return an instance of the bean * @throws BeansException if the bean could not be created */ @SuppressWarnings("unchecked") protected <T> T doGetBean( final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //1.获取对应的beanName ,BeanFactory去掉&,别名找到对应的BeanName final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. //2. 尝试从缓存中获取单例 Spring会,在Bean未建立完成的状况下,建立Bean的ObjectFactory对象,提前曝光,以方便解决循环依赖。 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } //根据bean实例获取对象,若是是FactoryBean 获取它建立的对象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. //3.原型依赖的检查,若是是原型,假设存在循环引用,抛出异常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. // 4.检查bean,是否认义在了BeanFactory中, BeanFactory parentBeanFactory = getParentBeanFactory(); // 若是父BeanFactory不为空&&当前并无beanDefinitionMap不包含, // 委托给父BeanFactory if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. //委托给,须要参数的 getBean方法 return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. // 委托给标准的getBean方法 return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { //不只是,类型检查,标记bean为建立 // 容许bean能够从新合并 markBeanAsCreated(beanName); } try { //5.将GernericBeanDefinition转换为RootBeanDefinition, //若是Bean有父Bean,时会合并父类的相关属性。 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that // the current bean depends on. // 6.保证bean的依赖先初始化了 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 对应@DependsOn 注解, /** * 检测是否存在 depends-on 循环依赖,若存在则抛异常。 * 好比 A 依赖 B, * B 又依赖 A,他们的配置以下: @Bean(name="a") @DependsOn("b")public A a () { return new A();} @Bean(name = "b") @DependsOn("a") public B b () { return new B(); } * a 要求 b 在其以前被建立,但 b 又要求 a 先于它 * 建立。这个时候造成了循环,对于 depends-on 循环,Spring 会直接 * 抛出异常 * *@see org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan */ if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } //注册,Dependent和Bean的关系 registerDependentBean(dep, beanName); try { //先建立Dependent getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. //7.建立Bean的实例 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); } 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 name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); 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); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. // 8.进行类型转换 // requiredType.isInstance(bean) 相似 bean instanceof requiredType // 为true表示能够直接返回,或强转 //clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj) //仅当obj not null if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
当看完主流程时,我有以下疑问:url
getObjectForBeanInstance和createBean的逻辑下一篇再聊,预计20190921前上传。 这里先说下2,4。spa
简单说,就是清除原有的RootBeanDefinition,再经过当前的多个GenericBeanDefinition合并成新的RootBeanDefinition,供BeanFactory使用。.net
若是有兴趣能够搜索prototype
org.springframework.beans.factory.config.BeanDefinition org.springframework.beans.factory.support.GenericBeanDefinition org.springframework.beans.factory.support.RootBeanDefinition
我最开始觉得是bean须要依赖,处理Autowired注解,然而不是。 利用IDEA查找了调用BeanDefinition的setDependsOn的地方,
发现了AnnotationConfigUtils.processCommonDefinitionAnnotations方法中如以下代码:
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); }
也就是说doGetBean中的
String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { ..... }
是对@DependOn注解的支持,我孤陋寡闻,工做中重来没有使用过@DependOn注解。从网上查阅了资料。
当时我查下的资料的url:https://blog.csdn.net/qq_30257149/article/details/88350320
@DependOn注解用来表示一个bean A的实例化依赖另外一个bean B的实例化, 可是A并不须要持有一个B的对象
读源码不容易,最开始我老是揪住一个方法不放,个把小时下来,已经不知道本身读到哪里了,后来老是囫囵吞枣,一味求快,好像看了不少,实际上什么也不知道。今年9月初,不知道是北京的天气变凉快了,仍是什么别的缘由,我本身也不清楚,居然能静下心来,不求快,一层一层读,一点一点翻译,天天仅读40分钟,总算感受是明白了点,不由感慨以下:
只抓细节太糊涂
囫囵吞枣净瞎看
静心慢读未必快
反正我是入门了