十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章主要讲解了“Spring Ioc中Bean的加载实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Ioc中Bean的加载实现方法”吧!
创新互联公司-专业网站定制、快速模板网站建设、高性价比秀英网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式秀英网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖秀英地区。费用合理售后完善,十多年实体公司更值得信赖。
代码:
//AbstractAutowireCapableBeanFactory.java protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved 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. //判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载 Class> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. //校验和准备Bean中的方法覆盖 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. //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象 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 { //创建Bean的入口 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException ex) { // A previously detected exception with proper bean creation context already... throw ex; } catch (ImplicitlyAppearedSingletonException ex) { // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry... throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
这段代码分为以下几个步骤:
判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
校验和准备Bean中的方法注入
如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
创建Bean
主要是获取bean的class,并设置到BeanDefinition中
主要是处理方法注入
代码:
public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists. //检测是否存在方法注入,并循环预处理方法注入 if (hasMethodOverrides()) { Setoverrides = getMethodOverrides().getOverrides(); synchronized (overrides) { //遍历处理 for (MethodOverride mo : overrides) { prepareMethodOverride(mo); } } } }
prepareMethodOverride(mo):
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() + "]"); } // 如果为1,则将注入方法标记为未重载 // 注意:当有多个重载方法时,为了确定调用哪个具体的方法,Spring对重载方法的参数解析是很复杂的 // 所以,如果注入方法没有被重载这里就将其标记,省去了对方法参数的解析过程,直接调用即可 else if (count == 1) { // Mark override as not overloaded, to avoid the overhead of arg type checking. mo.setOverloaded(false); } }
代码读到这里,大家可能有疑问,从代码上看明明是处理的方法重载,但是为什么处理的是方法注入呢?而且如果我们在bean里设置几个方法重载的话,hasMethodOverrides()
方法返回的是false。如果我们打开 AbstractBeanDefinition 类的 hasMethodOverrides() 方法,就能打消我们之前的疑问。
public boolean hasMethodOverrides() { return (this.methodOverrides != null && !this.methodOverrides.isEmpty()); }
其中methodOverrides
是做什么的呢?通过类名AbstractBeanDefinition我们可以发现,该类是BeanDefinition的一个子类,那么它保存的应该是我们解析到的beanDefinition,spring在解析配置文件的时候,如果发现配置了replace-method
或者lookup-method
那么,就会对应的标签解析,并存入到 AbstractBeanDefinition 的 methodOverrides 属性中,那么当bean实例化的时候,如果检测到了methodOverrides属性不为空,则动态的为当前bean生成代理并使用相应的拦截器对bean做处理,这里大家只要把概念搞清楚即可。
主要是对bean前置后置处理器的处理,给 BeanPostProcessors 后置处理器一个返回代理对象的机会
详细代码:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
如果代理对象不为空,则直接返回代理对象,这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()
和 applyBeanPostProcessorsAfterInitialization()
两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。
doCreateBean()
创建Bean
//真正创建Bean的方法 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. //BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { //单例模式,删除factoryBean缓存 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //使用合适的实例化策略来创建Bean:工厂方法、构造函数自动注入、简单初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } //从包装类中获取实例化的Bean final Object bean = instanceWrapper.getWrappedInstance(); //获取实例化对象的类型 Class> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. //检查是否有后置处理 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { //调用PostProcessor后置处理器,修改 BeanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. // 解决单例模式的循环依赖 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. //Bean对象的初始化,依赖注入在此触发 //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean Object exposedObject = bean; try { //将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象 populateBean(beanName, mbd, instanceWrapper); //初始化Bean对象 exposedObject = 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) { //获取指定名称的已注册的单例模式Bean对象 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { //根据名称获取的已注册的Bean和正在实例化的Bean是同一个 if (exposedObject == bean) { //当前实例化的Bean初始化完成 exposedObject = earlySingletonReference; } //当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); SetactualDependentBeans = new LinkedHashSet<>(dependentBeans.length); //获取当前Bean所依赖的其他Bean for (String dependentBean : dependentBeans) { //对依赖Bean进行类型检查 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."); } } } } // Register bean as disposable. //注册完成依赖注入的Bean try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
代码很长,不过别慌,我们来按步骤分析一波
如果是单例模式,从factoryBeanInstanceCache 缓存中获取BeanWrapper 实例对象并删除缓存
调用 createBeanInstance()
实例化 bean
(主要是将 BeanDefinition 转换为 BeanWrapper)
后置处理
单例模式的循环依赖处理
初始化 bean 实例对象
(属性填充)
依赖检查
注册 DisposableBean
doCreateBean()
完成 bean 的创建和初始化工作,内容太多,比较复杂,这里只列出大致流程,接下来我们将分几篇文章来分别阐述相关内容。
感谢各位的阅读,以上就是“Spring Ioc中Bean的加载实现方法”的内容了,经过本文的学习后,相信大家对Spring Ioc中Bean的加载实现方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!