Spring Bean生命周期

打印 上一主题 下一主题

主题 850|帖子 850|积分 2550

Spring Bean生命周期

本文基于图灵课堂周瑜老师的讲解整理,包括spring bean加载的过程,主要是扫描BeanDefinition以及初始化非懒加载单例Bean两部分,源码取自SpringFramework 5.3.22
1. Bean扫描

本小节介绍的是Spring从给定的扫描位置扫描到待加载的Bean,生成BeanDefinitionMap的过程
SpringBoot启动过程中使用的ApplicationContext是AnnotationConfigApplicationContext,而它初始化的时候会顺带初始化两个BeanDefinitionReader:AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,前者是可以直接通过给定的class注册Bean,后者则可以扫描给定目录下所有的目标Bean,下面着重介绍后者扫描Bean组件的过程。
ClassPathBeanDefinitionScanner扫描的入口是public int scan(String... basePackages),而真正做事情的是protected Set doScan(String... basePackages)方法,代码如下:
  1. /**<br>     * Perform a scan within the specified base packages,<br>     * returning the registered bean definitions.<br>     * <p>This method does <i>not</i> register an annotation config processor<br>     * but rather leaves this up to the caller.<br>     * @param basePackages the packages to check for annotated classes<br>     * @return set of beans registered if any for tooling registration purposes (never {@code null})<br>     */<br>protected Set<BeanDefinitionHolder> doScan(String... basePackages) {<br>        Assert.notEmpty(basePackages, "At least one base package must be specified");<br>        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();<br>        for (String basePackage : basePackages) {<br>            // 找到basePackage下的所有候选组件,这里只是把classname赋值给了BeanDefinition<br>            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);<br>            for (BeanDefinition candidate : candidates) {<br>                // 获取组件的scope,默认是单例的<br>                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);<br>                candidate.setScope(scopeMetadata.getScopeName());<br>                // 获取beanname<br>                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);<br>                if (candidate instanceof AbstractBeanDefinition) {<br>                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);<br>                }<br>                // 处理通用的注解<br>                if (candidate instanceof AnnotatedBeanDefinition) {<br>                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);<br>                }<br>                // 最后再对BeanDefinition做检查,看下是否有重名的<br>                if (checkCandidate(beanName, candidate)) {<br>                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);<br>                    definitionHolder =<br>                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);<br>                    beanDefinitions.add(definitionHolder);<br>                    registerBeanDefinition(definitionHolder, this.registry);<br>                }<br>            }<br>        }<br>        return beanDefinitions;<br>    }
复制代码
下面将以上部分代码展开去讲
1.1 扫描包下面的所有组件

即对应findCandidateComponents方法的操作,该方法如下:
  1.     /**<br>     * Scan the class path for candidate components.<br>     * @param basePackage the package to check for annotated classes<br>     * @return a corresponding Set of autodetected bean definitions<br>     */<br>    public Set<BeanDefinition> findCandidateComponents(String basePackage) {<br>        if (this.componentsIndex != null && indexSupportsIncludeFilters()) {<br>            return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);<br>        }<br>        else {<br>            return scanCandidateComponents(basePackage);<br>        }<br>    }
复制代码

  • 首先来判断是否有对应的索引,即看componentsIndex是否有值,它加载的是META-INF/spring.components中的信息,内容格式如下:
    1. com.sgw.demo=org.springframework.stereotype.Component
    复制代码
    之后,就加载这里的Bean组件,不去做扫描,对于项目过于庞大,扫描耗费时间的情况,可以考虑这种方案,个人感觉对于现在的微服务架构,这种应该没太多实际场景
  • 如果没有索引,即进入真正的扫描流程scanCandidateComponents,代码如下:
    1. private Set<BeanDefinition> scanCandidateComponents(String basePackage) {<br>    Set<BeanDefinition> candidates = new LinkedHashSet<>();<br>    try {<br>        // 根据传入的包名,得到对应的classpath中的路径<br>        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +<br>                resolveBasePackage(basePackage) + '/' + this.resourcePattern;<br>        // 获取该路径下的所有class文件<br>        Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);<br>        boolean traceEnabled = logger.isTraceEnabled();<br>        boolean debugEnabled = logger.isDebugEnabled();<br>        for (Resource resource : resources) {<br>            if (traceEnabled) {<br>                logger.trace("Scanning " + resource);<br>            }<br>            try {<br>                // 使用ASM读取class文件<br>                MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);<br>                // 判断是否是要扫描的组件<br>                if (isCandidateComponent(metadataReader)) {<br>                    ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);<br>                    // 设置resource文件<br>                    sbd.setSource(resource);<br>                    // 判断扫描到的组件是否是正常的类(是不是独立的,检查是不是接口、抽象类(带LookUp注解的除外))<br>                    if (isCandidateComponent(sbd)) {<br>                        if (debugEnabled) {<br>                            logger.debug("Identified candidate component class: " + resource);<br>                        }<br>                        candidates.add(sbd);<br>                    }<br>                    else {<br>                        if (debugEnabled) {<br>                            logger.debug("Ignored because not a concrete top-level class: " + resource);<br>                        }<br>                    }<br>                }<br>                else {<br>                    if (traceEnabled) {<br>                        logger.trace("Ignored because not matching any filter: " + resource);<br>                    }<br>                }<br>            }<br>            catch (FileNotFoundException ex) {<br>                if (traceEnabled) {<br>                    logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());<br>                }<br>            }<br>            catch (Throwable ex) {<br>                throw new BeanDefinitionStoreException(<br>                        "Failed to read candidate component class: " + resource, ex);<br>            }<br>        }<br>    }<br>    catch (IOException ex) {<br>        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);<br>    }<br>    return candidates;<br>}
    复制代码

    • 根据传入的包名,得到对应的classpath中的路径
      前面加上classpath*:前缀,后面加上**/*.class,同时把包名中的.替换成/
    • 基于第一步拼接的搜索路径,得到下面所有的class文件,并以Resource数组的形式返回
    • 遍历得到的Resource数组,使用ASM读取class文件
      有个问题是为什么这里已经取得了类名,不直接用jdk的classloader加载进去呢,原因是效率问题,把扫描到的类都加载上去第一没必要,第二浪费时间
    • 判断是否是要扫描的组件
      这里是基于exclude以及include两类filter以及conditional注解来做的,看下具体代码实现
      1.     /**<br>     * Determine whether the given class does not match any exclude filter<br>     * and does match at least one include filter.<br>     * @param metadataReader the ASM ClassReader for the class<br>     * @return whether the class qualifies as a candidate component<br>     */<br>    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {<br>        for (TypeFilter tf : this.excludeFilters) {<br>            if (tf.match(metadataReader, getMetadataReaderFactory())) {<br>                return false;<br>            }<br>        }<br>        for (TypeFilter tf : this.includeFilters) {<br>            if (tf.match(metadataReader, getMetadataReaderFactory())) {<br>                return isConditionMatch(metadataReader);<br>            }<br>        }<br>        return false;<br>    }
      复制代码
      这些是从ComponentScan这个注解中解析出来的,是includeFilters和excludeFilters这俩属性,平时我们什么都不配置,默认扫描的是@Component @Repository @Service @Controller 这些注解,它们是会默认出现在includeFilters中的。
      如果命中了includefilter,接下来检查是否有conditional注解,如果有,则判断是否满足条件。
    • 判断扫描到的组件是否是正常的类
      这里是有一套逻辑,因为一些内部类、抽象类、接口编译之后也会生成class文件,而这些文件到这一步是没有被过滤的,这里涉及到一个概念,说类是不是独立的,注释中是这么说的:
      Determine whether the underlying class is independent, i.e. whether it is a top-level class or a nested class (static inner class) that can be constructed independently of an enclosing class.
      即不依赖其他类也能正常被构建,因为后面扫描完成,有一个很重要的步骤,是实例化,而那些非静态的内部类、接口、抽象类是不能被实例化的,故这里排除在外。

1.2 依次处理扫描到的组件


  • 获取组件的scope
    通过解析scope注解获取,默认是单例属性


  • 获取BeanDefinition的名称,即BeanName,首先从注解中取,如果没有就基于类名生成一个,用到了Introspector.decapitalize(shortClassName)方法
  • 处理AbstractBeanDefinition ,设置BeanDefinition中的默认值
  • 解析bean的一些注解,并记录到BeanDefinition中,包括Lazy、Primary、DependsOn、Role、Description
  • 之后,再次检查对应的BeanDefinition是否已经被加载了,出现这种情况可能是同一个类被扫描到了两次,这里就是检查如果是有两个同名的,只能允许它们是同一个类被扫描了两次,如果是其他情况,即两个bean同名,那么直接报错
  • 都检查通过之后,注册该BeanDefinition,等待之后的处理
2. 非懒加载单例Bean的创建

本小节介绍在扫描完BeanDefinition之后的,在初始化的时候做的事情,对于每一个扫描到的BeanDefinition,合并成RootBeanDefinition,之后调用getSingleton,如果是单例非懒加载Bean,就实例化、初始化Bean,加载到单例池中。
这里是在ApplicitionContext的refresh()方法中调用的,其中有beanFactory.preInstantiateSingletons();这么一步,即初始化所有的非懒加载的单例Bean,具体实现如下:
  1.     public void preInstantiateSingletons() throws BeansException {<br>        if (logger.isTraceEnabled()) {<br>            logger.trace("Pre-instantiating singletons in " + this);<br>        }<br>​<br>        // Iterate over a copy to allow for init methods which in turn register new bean definitions.<br>        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.<br>        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);<br>​<br>        // Trigger initialization of all non-lazy singleton beans...<br>        for (String beanName : beanNames) {<br>            // 因为之前BeanDefinition存在继承的概念,这里是合并子BeanDefinition和父BeanDefinition<br>            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);<br>            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {<br>                // 非懒加载单例bean<br>                if (isFactoryBean(beanName)) {<br>                    // 处理工厂Bean<br>                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);<br>                    if (bean instanceof FactoryBean) {<br>                        FactoryBean<?> factory = (FactoryBean<?>) bean;<br>                        boolean isEagerInit;<br>                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {<br>                            isEagerInit = AccessController.doPrivileged(<br>                                    (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,<br>                                    getAccessControlContext());<br>                        }<br>                        else {<br>                            isEagerInit = (factory instanceof SmartFactoryBean &&<br>                                    ((SmartFactoryBean<?>) factory).isEagerInit());<br>                        }<br>                        if (isEagerInit) {<br>                            getBean(beanName);<br>                        }<br>                    }<br>                }<br>                else {<br>                    // 初始化Bean<br>                    getBean(beanName);<br>                }<br>            }<br>        }<br>​<br>        // Trigger post-initialization callback for all applicable beans...<br>        for (String beanName : beanNames) {<br>            Object singletonInstance = getSingleton(beanName);<br>            if (singletonInstance instanceof SmartInitializingSingleton) {<br>                StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")<br>                        .tag("beanName", beanName);<br>                SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;<br>                if (System.getSecurityManager() != null) {<br>                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {<br>                        smartSingleton.afterSingletonsInstantiated();<br>                        return null;<br>                    }, getAccessControlContext());<br>                }<br>                else {<br>                    smartSingleton.afterSingletonsInstantiated();<br>                }<br>                smartInitialize.end();<br>            }<br>        }<br>    }
复制代码
之后的核心实现在getBean(beanName)的doGetBean();方法中,如下:
  1. /**<br> * Return an instance, which may be shared or independent, of the specified bean.<br> * @param name the name of the bean to retrieve<br> * @param requiredType the required type of the bean to retrieve<br> * @param args arguments to use when creating a bean instance using explicit arguments<br> * (only applied when creating a new instance as opposed to retrieving an existing one)<br> * @param typeCheckOnly whether the instance is obtained for a type check,<br> * not for actual use<br> * @return an instance of the bean<br> * @throws BeansException if the bean could not be created<br> */<br>@SuppressWarnings("unchecked")<br>protected <T> T doGetBean(<br>      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)<br>      throws BeansException {<br>    // 处理BeanName,如果是前面加了&符号,去除之,如果是别名,得到其正式的名称<br>   String beanName = transformedBeanName(name);<br>   Object beanInstance;<br>​<br>    // 这里先试着获取下单例池中有没有对应的单例对象,如果有的话,就直接返回<br>   // Eagerly check singleton cache for manually registered singletons.<br>   Object sharedInstance = getSingleton(beanName);<br>   if (sharedInstance != null && args == null) {<br>      if (logger.isTraceEnabled()) {<br>         if (isSingletonCurrentlyInCreation(beanName)) {<br>            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +<br>                  "' that is not fully initialized yet - a consequence of a circular reference");<br>         }<br>         else {<br>            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");<br>         }<br>      }<br>      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);<br>   }<br>​<br>   else {<br>      // Fail if we're already creating this bean instance:<br>      // We're assumably within a circular reference.<br>      if (isPrototypeCurrentlyInCreation(beanName)) {<br>         throw new BeanCurrentlyInCreationException(beanName);<br>      }<br>​<br>       // 如果本bean工厂不存在传进来的BeanName,并且存在父工厂,则到父工厂中寻找<br>      // Check if bean definition exists in this factory.<br>      BeanFactory parentBeanFactory = getParentBeanFactory();<br>      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {<br>         // Not found -> check parent.<br>         String nameToLookup = originalBeanName(name);<br>         if (parentBeanFactory instanceof AbstractBeanFactory) {<br>            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(<br>                  nameToLookup, requiredType, args, typeCheckOnly);<br>         }<br>         else if (args != null) {<br>            // Delegation to parent with explicit args.<br>            return (T) parentBeanFactory.getBean(nameToLookup, args);<br>         }<br>         else if (requiredType != null) {<br>            // No args -> delegate to standard getBean method.<br>            return parentBeanFactory.getBean(nameToLookup, requiredType);<br>         }<br>         else {<br>            return (T) parentBeanFactory.getBean(nameToLookup);<br>         }<br>      }<br>​<br>      if (!typeCheckOnly) {<br>         markBeanAsCreated(beanName);<br>      }<br>​<br>      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")<br>            .tag("beanName", name);<br>      try {<br>         if (requiredType != null) {<br>            beanCreation.tag("beanType", requiredType::toString);<br>         }<br>          // 取合并之后的rootBeanDefinition<br>         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);<br>         checkMergedBeanDefinition(mbd, beanName, args);<br>​<br>          // 如果有被dependsOn注解修饰,优先初始化dependsOn中的bean<br>         // Guarantee initialization of beans that the current bean depends on.<br>         String[] dependsOn = mbd.getDependsOn();<br>         if (dependsOn != null) {<br>            for (String dep : dependsOn) {<br>               if (isDependent(beanName, dep)) {<br>                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,<br>                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");<br>               }<br>               registerDependentBean(dep, beanName);<br>               try {<br>                  getBean(dep);<br>               }<br>               catch (NoSuchBeanDefinitionException ex) {<br>                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,<br>                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);<br>               }<br>            }<br>         }<br>​<br>          // 之后基于不同的scope来创建bean<br>         // Create bean instance.<br>         if (mbd.isSingleton()) {<br>            sharedInstance = getSingleton(beanName, () -> {<br>               try {<br>                  return createBean(beanName, mbd, args);<br>               }<br>               catch (BeansException ex) {<br>                  // Explicitly remove instance from singleton cache: It might have been put there<br>                  // eagerly by the creation process, to allow for circular reference resolution.<br>                  // Also remove any beans that received a temporary reference to the bean.<br>                  destroySingleton(beanName);<br>                  throw ex;<br>               }<br>            });<br>            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);<br>         }<br>​<br>         else if (mbd.isPrototype()) {<br>            // It's a prototype -> create a new instance.<br>            Object prototypeInstance = null;<br>            try {<br>               beforePrototypeCreation(beanName);<br>               prototypeInstance = createBean(beanName, mbd, args);<br>            }<br>            finally {<br>               afterPrototypeCreation(beanName);<br>            }<br>            beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);<br>         }<br>​<br>         else {<br>            String scopeName = mbd.getScope();<br>            if (!StringUtils.hasLength(scopeName)) {<br>               throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");<br>            }<br>            Scope scope = this.scopes.get(scopeName);<br>            if (scope == null) {<br>               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");<br>            }<br>            try {<br>               Object scopedInstance = scope.get(beanName, () -> {<br>                  beforePrototypeCreation(beanName);<br>                  try {<br>                     return createBean(beanName, mbd, args);<br>                  }<br>                  finally {<br>                     afterPrototypeCreation(beanName);<br>                  }<br>               });<br>               beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);<br>            }<br>            catch (IllegalStateException ex) {<br>               throw new ScopeNotActiveException(beanName, scopeName, ex);<br>            }<br>         }<br>      }<br>      catch (BeansException ex) {<br>         beanCreation.tag("exception", ex.getClass().toString());<br>         beanCreation.tag("message", String.valueOf(ex.getMessage()));<br>         cleanupAfterBeanCreationFailure(beanName);<br>         throw ex;<br>      }<br>      finally {<br>         beanCreation.end();<br>      }<br>   }<br>​<br>   return adaptBeanInstance(name, beanInstance, requiredType);<br>}
复制代码

  • 处理BeanName
    如果是前面加了&符号,去除之,如果是别名,得到其正式的名称


  • 先试着获取下单例池中有没有对应的单例对象,如果有的话,就直接返回
  • 如果本bean工厂不存在传进来的BeanName,并且存在父工厂,则到父工厂中寻找
  • 如果有被dependsOn注解修饰,优先初始化dependsOn中的bean
  • 之后基于不同的scope来创建bean
    这里的scope主要有以下几种

    • singleton


    • prototype
    • requestScope
      即同一个request中的bean要保持一致


    • sessionScope
      即同一个session中的bean要保持一致
    之后的两个是通过设置request和session中的属性来实现的
    以上的情况,需要真正创建bean的时候,就会落到AbstractAutowireCapableBeanFactory中实现的createBean中,
    首先加载BeanClass,resolveBeanClass(mbd, beanName),把bean加载到对应的classLoader中。
    实例化
    这里是bean构造的第一个扩展点,如下:
    1. try {<br>   // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.<br>   Object bean = resolveBeforeInstantiation(beanName, mbdToUse);<br>   if (bean != null) {<br>      return bean;<br>   }<br>}<br>catch (Throwable ex) {<br>   throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,<br>         "BeanPostProcessor before instantiation of bean failed", ex);<br>}
    复制代码
    这里是实例化之前调用的接口,注释中看到的就是给BeanPostProcessor接口的实现类一个构造代理bean的机会,实现偷天幻日的机会。具体如下:
    1. /**<br> * Apply before-instantiation post-processors, resolving whether there is a<br> * before-instantiation shortcut for the specified bean.<br> * @param beanName the name of the bean<br> * @param mbd the bean definition for the bean<br> * @return the shortcut-determined bean instance, or {@code null} if none<br> */<br>@Nullable<br>protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {<br>   Object bean = null;<br>   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {<br>      // Make sure bean class is actually resolved at this point.<br>      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {<br>         Class<?> targetType = determineTargetType(beanName, mbd);<br>         if (targetType != null) {<br>            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);<br>            if (bean != null) {<br>               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);<br>            }<br>         }<br>      }<br>      mbd.beforeInstantiationResolved = (bean != null);<br>   }<br>   return bean;<br>}
    复制代码
    首先会看,是否已经实例化了,如果没有实例化,就依次调用已经实现了的postProcessBeforeInstantiation接口,Spring中的AOP即利用的这里的扩展点,将命中切面表达式的Bean替换成对应的代理类,AOP实现的接口是AbstractAutoProxyCreator。
    之后确认是走正常的Bean初始化流程,即进入doCreateBean方法,具体实现如下,这里实现了bean生命周期中的多个重要的扩展点,包括依赖注入、初始化前后、实例化后、初始化等:
    1. /**<br> * Actually create the specified bean. Pre-creation processing has already happened<br> * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.<br> * <p>Differentiates between default bean instantiation, use of a<br> * factory method, and autowiring a constructor.<br> * @param beanName the name of the bean<br> * @param mbd the merged bean definition for the bean<br> * @param args explicit arguments to use for constructor or factory method invocation<br> * @return a new instance of the bean<br> * @throws BeanCreationException if the bean could not be created<br> * @see #instantiateBean<br> * @see #instantiateUsingFactoryMethod<br> * @see #autowireConstructor<br> */<br>protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)<br>      throws BeanCreationException {<br>​<br>   // Instantiate the bean.<br>   BeanWrapper instanceWrapper = null;<br>   if (mbd.isSingleton()) {<br>      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);<br>   }<br>   if (instanceWrapper == null) {<br>      instanceWrapper = createBeanInstance(beanName, mbd, args);<br>   }<br>   Object bean = instanceWrapper.getWrappedInstance();<br>   Class<?> beanType = instanceWrapper.getWrappedClass();<br>   if (beanType != NullBean.class) {<br>      mbd.resolvedTargetType = beanType;<br>   }<br>​<br>    // 调用MergedBeanDefinitionPostProcessor中的postProcessMergedBeanDefinition<br>   // Allow post-processors to modify the merged bean definition.<br>   synchronized (mbd.postProcessingLock) {<br>      if (!mbd.postProcessed) {<br>         try {<br>            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);<br>         }<br>         catch (Throwable ex) {<br>            throw new BeanCreationException(mbd.getResourceDescription(), beanName,<br>                  "Post-processing of merged bean definition failed", ex);<br>         }<br>         mbd.postProcessed = true;<br>      }<br>   }<br>​<br>   // Eagerly cache singletons to be able to resolve circular references<br>   // even when triggered by lifecycle interfaces like BeanFactoryAware.<br>   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&<br>         isSingletonCurrentlyInCreation(beanName));<br>   if (earlySingletonExposure) {<br>      if (logger.isTraceEnabled()) {<br>         logger.trace("Eagerly caching bean '" + beanName +<br>               "' to allow for resolving potential circular references");<br>      }<br>      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));<br>   }<br>​<br>   // Initialize the bean instance.<br>   Object exposedObject = bean;<br>   try {<br>      populateBean(beanName, mbd, instanceWrapper);<br>      exposedObject = initializeBean(beanName, exposedObject, mbd);<br>   }<br>   catch (Throwable ex) {<br>      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {<br>         throw (BeanCreationException) ex;<br>      }<br>      else {<br>         throw new BeanCreationException(<br>               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);<br>      }<br>   }<br>​<br>   if (earlySingletonExposure) {<br>      Object earlySingletonReference = getSingleton(beanName, false);<br>      if (earlySingletonReference != null) {<br>         if (exposedObject == bean) {<br>            exposedObject = earlySingletonReference;<br>         }<br>         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {<br>            String[] dependentBeans = getDependentBeans(beanName);<br>            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);<br>            for (String dependentBean : dependentBeans) {<br>               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {<br>                  actualDependentBeans.add(dependentBean);<br>               }<br>            }<br>            if (!actualDependentBeans.isEmpty()) {<br>               throw new BeanCurrentlyInCreationException(beanName,<br>                     "Bean with name '" + beanName + "' has been injected into other beans [" +<br>                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +<br>                     "] in its raw version as part of a circular reference, but has eventually been " +<br>                     "wrapped. This means that said other beans do not use the final version of the " +<br>                     "bean. This is often the result of over-eager type matching - consider using " +<br>                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");<br>            }<br>         }<br>      }<br>   }<br>​<br>   // Register bean as disposable.<br>   try {<br>      registerDisposableBeanIfNecessary(beanName, bean, mbd);<br>   }<br>   catch (BeanDefinitionValidationException ex) {<br>      throw new BeanCreationException(<br>            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);<br>   }<br>​<br>   return exposedObject;<br>}
    复制代码
    包含的扩展点

    • 调用MergedBeanDefinitionPostProcessor中的postProcessMergedBeanDefinition
      这里校验一些关于BeanDefinition的数据,同时也可以做些改动
      CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor都实现了这个扩展点,这里是做一些注解的前置校验的工作


    • 调用InstantiationAwareBeanPostProcessor中的postProcessAfterInstantiation实例化之后的扩展点
      1. // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the<br>// state of the bean before properties are set. This can be used, for example,<br>// to support styles of field injection.
      复制代码


    • 做Spring自带的依赖注入
    • 调用InstantiationAwareBeanPostProcessor的postProcessProperties以及postProcessPropertyValues(废弃)接口做依赖注入
    • 调用setBeanName、setBeanClassLoader、setBeanFactory
    • 调用BeanPostProcessor中的postProcessBeforeInitialization接口,初始化前的扩展点
    • 调用InitializingBean中的afterPropertiesSet接口
    • 调用初始化方法
    • 调用BeanPostProcessor中的postProcessAfterInitialization接口,初始化后的扩展点
    • 初始化结束
    •  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表