zoukankan      html  css  js  c++  java
  • Spring Boot源码(六):Bean的创建详解

    继续之前的项目:

    People加上无参构造方法:

    @Component
    public class People {
    //    private User user;
        public People(){
            System.out.println("create People");
        }
    }

    在refresh()方法中,打上断点:

     在此方法之前,People对象都没有被创建(没有调用构造方法)

    关注此方法:

        /**
         * Finish the initialization of this context's bean factory,
         * initializing all remaining singleton beans.
         */
        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            // Initialize conversion service for this context.
            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));
            }
    
            // Register a default embedded value resolver if no bean post-processor
            // (such as a PropertyPlaceholderConfigurer bean) registered any before:
            // at this point, primarily for resolution in annotation attribute values.
            if (!beanFactory.hasEmbeddedValueResolver()) {
                beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
            }
    
            // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
            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);
    
            // Allow for caching all bean definition metadata, not expecting further changes.
            beanFactory.freezeConfiguration();
    
            // Instantiate all remaining (non-lazy-init) singletons.
            beanFactory.preInstantiateSingletons();
        }

    此方法的注释也说明了。这里只会实例化,不是懒加载,是单例的bean。

    执行此方法后控制台才输出:

    create People

    这说明对象的创建是在此方法(DefaultListableBeanFactory类)中:

    @Override
        public void preInstantiateSingletons() throws BeansException {
            if (logger.isDebugEnabled()) {
                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);
    
            // Trigger initialization of all non-lazy singleton beans...
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    if (isFactoryBean(beanName)) {
                        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                        if (bean instanceof FactoryBean) {
                            final FactoryBean<?> factory = (FactoryBean<?>) bean;
                            boolean isEagerInit;
                            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                                isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                                ((SmartFactoryBean<?>) factory)::isEagerInit,
                                        getAccessControlContext());
                            }
                            else {
                                isEagerInit = (factory instanceof SmartFactoryBean &&
                                        ((SmartFactoryBean<?>) factory).isEagerInit());
                            }
                            if (isEagerInit) {
                                getBean(beanName);
                            }
                        }
                    }
                    else {
                        getBean(beanName);
                    }
                }
            }
    
            // Trigger post-initialization callback for all applicable beans...
            for (String beanName : beanNames) {
                Object singletonInstance = getSingleton(beanName);
                if (singletonInstance instanceof SmartInitializingSingleton) {
                    final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                    if (System.getSecurityManager() != null) {
                        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }, getAccessControlContext());
                    }
                    else {
                        smartSingleton.afterSingletonsInstantiated();
                    }
                }
            }
        }

    DefaultListableBeanFactory可以说是spring的容器,里面有各种map属性,例如beanDefinitionMap,beanDefinitionNames:

    这里我们使用条件断点(右击断点),因为我们只关注自己的People类,而beanDefinitionMap中有spring自己的类,一个一个遍历断点太麻烦:

     

    遍历此map,用beanName(key)拿到对应的beanDefinition(value);

    这里拿到了People的BeanDefinition对象,可以看到spring默认的scope就是singleton,不是懒加载

    判断 不为抽象类,是单例,不是懒加载

     再判断是否为Factorybean,很显然我们的People不是:

     直接进入else:

     

     首先去拿有没有对象,如果没有再创建。

     getSingleton()是一个比较重要的方法。

    @Nullable
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null && allowEarlyReference) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
            return singletonObject;
        }

     isSingletonCurrentlyIncreation()这个方法这里为false,大概意思当前是否是创建对象的过程。主要可以去解决循环依赖,之后再说,详见Spring Boot源码(七):循环依赖

     上面又调用了一次getSingleton方法,还用了lambda表达式,具体创建bean就是createBean()方法了。

  • 相关阅读:
    luoguP3806 【模板】点分治1
    BZOJ 4176: Lucas的数论 莫比乌斯反演 + 杜教筛
    BZOJ 3994: [SDOI2015]约数个数和 莫比乌斯反演
    CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心
    BZOJ 2226: [Spoj 5971] LCMSum 莫比乌斯反演 + 严重卡常
    BZOJ 4408: [Fjoi 2016]神秘数 主席树 + 神题
    BZOJ 4804: 欧拉心算 欧拉函数
    BZOJ 3930: [CQOI2015]选数 莫比乌斯反演 + 杜教筛
    html基础总结
    对于房天下租房信息进行爬取
  • 原文地址:https://www.cnblogs.com/SunSAS/p/12304176.html
Copyright © 2011-2022 走看看