spring of finishBeanFactoryInitialization analysis method

spring Source Version 5.0.5

Outline

        The method instantiates all of the remaining non-lazy loading singleton bean. In addition to some internal bean, bean implements the BeanFactoryPostProcessor interface implements BeanPostProcessor bean interface, other non-lazy loading singleton bean will be instantiated in this method, and this method is triggered BeanPostProcessor in.

analysis

        Tracking to AbstractApplicationContext.refresh () method, find the code finishBeanFactoryInitialization (beanFactory) see the implementation.

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        // 1.初始化此上下文的转换服务
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // the Register A default Embedded value the Resolver IF NO POST-bean Processor
         // (SUCH AS A PropertyPlaceholderConfigurer bean) the before the any Registered:
         // AT the this Point, the Primarily for Resolution in Annotation attribute values.
         // 2. If you have not registered before beanFactory value resolver embedded, embedding the registered default value resolver: mainly used to resolve annotation attribute value 
        IF (! beanFactory.hasEmbeddedValueResolver ()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        // 3.初始化LoadTimeWeaverAware Bean实例对象
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // the Allow for Caching All the Metadata Definition bean, not expecting Further Changes.
         // 4. freeze all bean definitions, registration bean definitions will not be modified or further post-treatment, because soon to create a Bean instance object 
        beanFactory.freezeConfiguration () ;

        // . Instantiate All Remaining (non-the lazy-the init) singletons
         // 5. The instances of all remaining (non-lazy loading) singleton object 
        beanFactory.preInstantiateSingletons ();
    }

Continue to follow the DefaultListableBeanFactory # preInstantiateSingletons

    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // the Trigger All non-Initialization of the lazy Singleton Beans ...
         // traverse beanNames, triggers all non-lazy loading singleton bean initialization 
        for (String the beanName: the beanNames) {
            BD RootBeanDefinition = getMergedLocalBeanDefinition (the beanName);
             // Bean Example: not an abstract class is a single embodiment && && not lazily 
            IF (bd.isAbstract () && bd.isSingleton () &&!! {Bd.isLazyInit ())
               // Analyzing beanName corresponding bean whether FactoryBean 
                iF (isFactoryBean (beanName)) {
                   // by getBean (& beanName) is FactoryBean get itself; by the getBean (beanName) is to get the FactoryBean bean instance 
                    Object bean = getBean (FACTORY_BEAN_PREFIX + the beanName);
                     IF (the bean the instanceof the FactoryBean) {
                         Final <?> = the FactoryBean Factory (the FactoryBean <?>) The bean;
                         // determine whether the desired eagerly FactoryBean initialization 
                        Boolean isEagerInit;
                         IF ! (Of System.getSecurityManager () = null && Factory the instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean (beanName);
                        }
                    }
                }
                the else {
                   // if not beanName corresponding bean FactoryBean, just ordinary Bean, bean instance by obtaining beanName 
                    the getBean (beanName);
                }
            }
        }

        ......
    }

To understand the difference FactoryBean and the Bean

        Generally, Spring reflection to specify a class by using the bean class to instantiate bean. The FactoryBean is a special kind of bean, it is a bean factory, you can create your own bean instance, if a class implements FactoryBean interface, you can define your own class method creates an instance of an object, only to realize it's getObject () method.

Note: Many middleware use FactoryBean be extended.

It introduces several important cache:

  • mergedBeanDefinitions cache: beanName -> Merge bean definition.
  • beanDefinitionMap 缓存:beanName -> BeanDefinition。
  • singletonObjects Cache: beanName -> bean singleton object.
  • earlySingletonObjects Cache: beanName -> singleton bean object, the cache is stored in early bean singleton objects, attributes may be understood to be filled has not been initialized.
  • singletonFactories 缓存:beanName -> ObjectFactory。
  • singletonsCurrentlyInCreation cache: currently creating singleton bean object beanName collection.

Inheritance track to create the bean AbstractBeanFactory # doGetBean

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        // parse the beanName, primarily to resolve aliases with, minus the prefix FactoryBean the "&" 
        Final String the beanName = transformedBeanName (name);
        Object bean;

        // . Eagerly Check Singleton Cache for singletons Manually Registered
         // try to obtain a corresponding instance beanName from the cache, to solve the circular dependency problem by caching 
        Object sharedInstance = getSingleton (beanName);
         IF (! SharedInstance = null && args == null ) {
             IF (logger.isDebugEnabled ()) {
                 IF (isSingletonCurrentlyInCreation (the beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // Returns beanName corresponding instance of an object (mainly for special treatment of FactoryBean, Common Bean will directly return sharedInstance itself) 
            the bean = getObjectForBeanInstance (sharedInstance, name, beanName, null );
        }

        the else {
             // the Fail IF WE're already Creating the this instance the bean:
             // . We're assumably WITHIN A Circular Reference
             // scope dependency checking a cyclic non-single prototype Example: if beanName Bean instance is already created in the At this point we have to once again create beanName instance, represents the emergence of a cycle of dependence, need to throw an exception.
            // Example: If there exists A property of B, B of A has property, then when dependency injection and they will produce when A is not yet complete because you created for the creation of B returns again to create an A, resulting in circulation dependent 
            IF (isPrototypeCurrentlyInCreation (the beanName)) {
                 the throw  new new BeanCurrentlyInCreationException (the beanName);
            }

            // the Check IF EXISTS Definition bean in the this Factory. 
            The BeanFactory parentBeanFactory = getParentBeanFactory ();
             // if parentBeanFactory exists, and no beanName BeanFactory Bean definitions exist in the current, the attempt to obtain the bean instance from parentBeanFactory 
            IF (parentBeanFactory =! Null &&! containsBeanDefinition (the beanName)) {
                 // . Not found -> Check parent 
                String nameToLookup = originalBeanName (name);
                 IF (parentBeanFactory the instanceof AbstractBeanFactory) {
                     return ((AbstractBeanFactory) parentBeanFactory) .doGetBean (
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            IF (! typeCheckOnly) {
               // if not only do the type of detection, but to create a bean instance, where you want to put alreadyCreated beanName cache 
                markBeanAsCreated (beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee Your Current Initialization of Beans The bean that The depends ON.
                 // get the name of the current collection bean bean dependent, before their instantiation, their need to instantiate dependency bean, such as the use @DependsOn 
                String [] The dependsOn = MBD .getDependsOn ();
                 IF (The dependsOn =! null ) {
                     for (DEP String: The dependsOn) {
                         IF (isDependent (the beanName, DEP)) {
                             the throw  new new BeanCreationException (mbd.getResourceDescription (), the beanName,
                                     "Circular Relationship The depends BETWEEN ON- ' "+ the beanName +"' and ' "+ DEP +"' " );
                        }
                        registerDependentBean (dep, beanName);
                        try {
                            getBean (dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // the Create bean instance. 
                IF (mbd.isSingleton ()) {
                    // scope of creating a singleton bean (the ObjectFactory a new, and rewrites the getObject method, create the bean inside 
                    sharedInstance = getSingleton (beanName, () -> {
                         the try {
                             return createBean (the 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;
                        }
                    });
                    // Returns beanName instance object corresponding to 
                    the bean = getObjectForBeanInstance (sharedInstance, name, beanName, MBD);
                }

                // Other non-singleton temporarily Analysis 
                ......
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        ......
        return (T) bean;
    }

查看DefaultSingletonBeanRegistry#getSingleton

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull (beanName, "Not Bean name MUST BE null" );
         the synchronized ( the this .singletonObjects) {
             // first check whether the corresponding beanName bean instance exists in the cache, if it already exists, the process directly returns 
            Object singletonObject = the this . singletonObjects.get (the beanName);
             IF (singletonObject == null ) {
                 IF ( the this .singletonsCurrentlyInDestruction) {
                     the throw  new new BeanCreationNotAllowedException (the beanName,
                             "the Singleton Not allowed the while the bean Creation of singletons are in the this Factory Destruction" +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                // create a single embodiment before the operation, is preparing the bean into a created singletonsCurrentlyInCreation Set, reported abnormal if the repetition
                 // if there is a circular dependency when the constructor (A (B b), B (C c), C (A a)), will be reported at this point exception 
                beforeSingletonCreation (the beanName);
                 Boolean newSingleton = to false ;
                 Boolean recordSuppressedExceptions = ( the this .suppressedExceptions == null );
                 IF (recordSuppressedExceptions) {
                     the this .suppressedExceptions = new new a LinkedHashSet <> ( );
                }
                the try {
                     // perform acquisition method getObject singletonFactory bean instance, the method is performed incoming createBean 
                    singletonObject = singletonFactory.getObject ();
                    newSingleton = true;
                }
                
                ......
                
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // Create operation after a single embodiment, are removed singletonsCurrentlyInCreation 
                    afterSingletonCreation (beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

 

 

Inheritance tracking AbstractAutowireCapableBeanFactory # createBean

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        ......
        
        the try {
             // verification and preparation method of covering (for marking and authentication attributes override) 
            mbdToUse.prepareMethodOverrides ();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        the try {
             // Give A Chance to return BeanPostProcessors A Proxy INSTEAD The target of bean instance.
             // treatment before instantiation, if implemented InstantiationAwareBeanPostProcessor BeanPostProcessor can return to the real bean instance 
            Object bean = resolveBeforeInstantiation (the beanName, mbdToUse);
             IF (the bean =! null ) {
                 return the bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        the try {
             // Create instance Bean (Bean created the method generally true) 
            Object beanInstance = doCreateBean (the beanName, mbdToUse, args);
             IF (logger.isDebugEnabled ()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        ......
    }

Treatment before instantiation, InstantiationAwareBeanPostProcessor a chance to return a proxy object instead of the real bean instance to skip the Spring default instantiation process, to "short circuit" effect. A method of performing InstantiationAwareBeanPostProcessor will postProcessBeforeInstantiation, the method may return the proxy bean instance, skipping Spring default instantiation process.

 

Guess you like

Origin www.cnblogs.com/grasp/p/11971887.html