isTypeMatch()方法中的部分代码
public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException { // 对beanName进行处理,将开头的 & 符过滤 String beanName = transformedBeanName(name); // 从spring容器中获取单实例Bean,由于spring容器启动时已经将单实例Bean进行了实例化, // 所以此时可以直接在容器中得到Bean实例 Object beanInstance = getSingleton(beanName, false); if (beanInstance != null && beanInstance.getClass() != NullBean.class) { // 获取到Bean实例后,判断是否为工厂Bean if (beanInstance instanceof FactoryBean) { // 如果是工厂Bean,并且获取的beanName不是以&符开头 if (!BeanFactoryUtils.isFactoryDereference(name)) { // 将实例强转为 FactoryBean 并调用 FactoryBean接口的getObjectType()方法, // 获取工厂Bean所生产的实例类型 Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance); // 判断工厂Bean生产的实例类型与传入的类型是否匹配 return (type != null && typeToMatch.isAssignableFrom(type)); } else { return typeToMatch.isInstance(beanInstance); } } // ...省略代码... } // ...省略代码... }getTypeForFactoryBean()方法中的代码
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) { try { if (System.getSecurityManager() != null) { return AccessController.doPrivileged((PrivilegedAction<Class<?>>) factoryBean::getObjectType, getAccessControlContext()); } else { // 直接调用 FactoryBean 接口的 getObjectType()方法,获取生产的类型 return factoryBean.getObjectType(); } } catch (Throwable ex) { // Thrown from the FactoryBean's getObjectType implementation. logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " + "that it should return null if the type of its object cannot be determined yet", ex); return null; } }以上便是getBeanNamesForType()方法经过的部分重要代码
由此可以看出,当我们想要获取BikeFactoryBean本身的beanName时,doGetBeanNamesForType方法内部将bikeFactoryBean前添加了&符前缀,于是便获取到了&bikeFactoryBean;
当我们想要获取Bike类型的beanName时,spring会通过容器遍历已经注册的所有的beanNames,然后根据beanName及对应的Bean定义信息BeanDefinition进行判断过滤,并且对于所有的工厂Bean,会获取spring容器中已经实例化的Bean对象,调用 FactoryBean 接口的 getObjectType()方法,得到工厂Bean所生产的实例类型,然后与Bike.class相比较,如果匹配,则将此beanName保存到结果集中,最后返回。所以,当我们想要获取Bike类型的beanName时,从spring容器中便可以找到bikeFactoryBean。
从spring容器中获取到beanName后,我们继续获取Bike实例
从前文中引导类的代码可以看出,获取Bike实例有两种方式,跟踪源码可以发现,根据Bike类型获取实例时,spring实际是通过第二步获取到beanName后再最终调用doGetBean方法获取实例对象。下面看看部分源码
从上面的代码可以看出,获取Bike实例的具体代码还在getObjectForBeanInstanc()方法内部,我们继续查看
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 判断beanName是否是以&符开头的 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } } // 根据beanName从spring容器中获取的Bean实例如果不是工厂Bean,或者beanName是以&符开头,就直接返回这个Bean实例 // 当我们获取Bike类型的实例时,beanName为“bikeFactoryBean”, // beanInstance为“BikeFactoryBean”类型,是一个工厂Bean,所以条件不满足,继续向下走 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { // 根据beanName从缓存中获取Bean实例,第一次来获取Bike实例时为空, // factoryBeanObjectCache.get(beanName); // 后续再获取时,便可以在此获得到,然后返回 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // 将获取的工厂Bean强转为 FactoryBean 类型,以便下面调用其getObject()方法获取对象 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // 获取bean定义信息 if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); //在此方法内部调用 FactoryBean 接口的 getObject()方法获取对象 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }