• [Re] Spring-4(SourceCode)


    1. 引入

    • IOC
      • IOC 是一个容器
      • 容器启动的时候创建所有单实例对象
      • 我们可以直接从容器中获取到这个对象
    • Spring IOC
      • IOC 容器的启动过程?启动期间都做了什么(什么时候创建所有单实例bean)
      • IOC 是如何创建这些单实例 bean,并如何管理的,到底保存在了那里?

    2. ClassPathXMLApplicationContext

    public ClassPathXmlApplicationContext(String[] configLocations,
            boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh(); // 所有单实例 bean 创建完成
        }
    }
    
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
    

    3. AbstractApplicationContext

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();
    
            // Tell the subclass to refresh the internal bean factory.
            // Spring 解析 XML 配置文件,将要创建的所有 bean 的配置信息保存起来
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);
    
            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
    
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // Register bean processors that intercept bean creation.
                // 注册Spring内置的bean后置处理器
                registerBeanPostProcessors(beanFactory);
    
                // Initialize message source for this context.
                // 用来支持国际化功能的
                initMessageSource();
    
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
    
                // Initialize other special beans in specific context subclasses.
                // 留给子类的
                onRefresh();
    
                // Check for listener beans and register them.
                registerListeners();
    
                // Instantiate all remaining (non-lazy-init) singletons.
                // 初始化所有单实例 bean ====> Step Into
                finishBeanFactoryInitialization(beanFactory);
    
                // Last step: publish corresponding event.
                finishRefresh();
    
            } catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
    
                // Reset 'active' flag.
                cancelRefresh(ex);
    
                // Propagate exception to caller.
                throw ex;
            }
        }
    }
    
    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));
        }
    
        // 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.
        // 初始化所有单实例 bean ====> Step Into
        beanFactory.preInstantiateSingletons();
    }
    

    4. DefaultListableBeanFactory

    @Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }
        // 所有要创建的 bean 的 id
        List<String> beanNames;
        synchronized (this.beanDefinitionMap) {
            // 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.
            beanNames = new ArrayList<String>(this.beanDefinitionNames);
        }
        // 按顺序创建 bean
        for (String beanName : beanNames) {
            // 根据 beanId 获取到 bean 的定义信息
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            // 如果 bean (不是抽象的 && bean 是单例的 && 不是懒加载的)
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 如果是工厂 bean(实现了 FactoryBean 接口的 bean)
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                                @Override
                                public Boolean run() {
                                    return ((SmartFactoryBean<?>) factory).isEagerInit();
                                }
                            }, getAccessControlContext());
                    } else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                } else {
                    getBean(beanName); // core!!!
                }
            }
        }
    }
    

    5. AbstractBeanFactory

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    
    protected <T> T doGetBean(final String name, final Class<T> requiredType
            , final Object[] args, boolean typeCheckOnly) throws BeansException {
    
        final String beanName = transformedBeanName(name);
        Object bean;
    
        // 先从已经注册的所有单实例 bean 中看有没有这个 bean (第一次肯定没有)
        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(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 + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
    
        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
    
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                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) {
                markBeanAsCreated(beanName);
            }
    
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // Guarantee initialization of beans that the current bean depends on.
                // 拿到创建当前 bean 之前需要提前创建的 bean → depends-on 属性
                String[] dependsOn = mbd.getDependsOn();
                // 如果有,就循环创建
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException("Circular depends-on relationship between '" +
                            beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean); // 创建
                    }
                }
    
                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                return createBean(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;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
    
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
    
                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName, "Scope '" + scopeName
                            + "' is not active for the current thread; consider defining a scoped "
                            + "proxy for this bean if you intend to refer to it from a singleton", ex);
                    }
                }
            } 
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
    
        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type [" +
                    ClassUtils.getQualifiedName(requiredType) + "]", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }
    

    6. DefaultSingletonBeanRegistry

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized (this.singletonObjects) {
            // 先从一个地方把这个 bean 拿出来
            /** Cache of singleton objects: bean name --> bean instance */
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                    "Singleton bean creation not allowed while the singletons of this factory are in 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 + "'");
                }
                beforeSingletonCreation(beanName);
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<Exception>();
                }
                try {
                    // bean 创建出来了!!!
                    singletonObject = singletonFactory.getObject();
                } catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                // 把 bean 对象加入 singletonObjects 这个 Map 中
                addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }
    
    • 创建好的对象最终会保存在一个 Map 中。IOC 容器之一:保存单实例 bean 的 ConcurrentHashMap,名为 singletonObjects
    • getBean 的时候,如果是单实例 bean,直接找 singletonObjects 这个 Map 要

    7. BeanFactory 和 ApplicationContext 区别

    • BeanFactory 是最底层的接口,ApplicationContext 是留给程序员使用的 IOC 容器接口;ApplicationContext 是 BeanFactory 的子接口。
    • BeanFactory(对象创建)
      • 是 bean 工厂接口,负责创建 bean 实例
      • 容器中保存所有单例 bean 的其实是一个 Map
    • ApplicationContext(对象之间的动态装配、管理)
      • 是 IOC 容器接口,更多的负责容器功能的实现
      • 可以基于 BeanFactory 创建好的 bean 之上,完成强大的容器功能
      • 容器从 Map 中获取这个 bean,继而进行 DI,AOP 等操作
    • Spring 里面最大的模式就是【工厂模式】。BeanFactory 如字面意思,就是一个 bean 工厂,根据用户提供的配置信息,创建 bean。

    8. IOC 容器创建和销毁的时机

    • 项目启动:IOC 容器创建
    • 项目关闭:IOC 容器销毁

    ContextLoaderListener

    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
        public ContextLoaderListener() {}
    
        public ContextLoaderListener(WebApplicationContext context) {
            super(context);
        }
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
            initWebApplicationContext(event.getServletContext());
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent event) {
            closeWebApplicationContext(event.getServletContext());
            ContextCleanupListener.cleanupAttributes(event.getServletContext());
        }
    }
    

    ContextLoader

    /**
     * The root WebApplicationContext instance that this loader manages.
     * WebApplicationContext extends ApplicationContext
     */
    private WebApplicationContext context;
    
    public static WebApplicationContext getCurrentWebApplicationContext() {
        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
        if (ccl != null) {
            WebApplicationContext ccpt = currentContextPerThread.get(ccl);
            if (ccpt != null) {
                return ccpt;
            }
        }
        return currentContext;
    }
    
    /**
     * Initialize Spring's web application context for the given servlet context,
     * using the application context provided at construction time, or creating a new one
     */
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        if (servletContext.getAttribute(WebApplicationContext
                .ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            throw new IllegalStateException(...);
        }
    
        Log logger = LogFactory.getLog(ContextLoader.class);
        servletContext.log("Initializing Spring root WebApplicationContext");
        if (logger.isInfoEnabled()) {
            logger.info("Root WebApplicationContext: initialization started");
        }
        long startTime = System.currentTimeMillis();
    
        // 包裹如下代码的 try...catch 已被省略
        // Store context in local instance variable, to guarantee that
        // it is available on ServletContext shutdown.
        if (this.context == null) {
            this.context = createWebApplicationContext(servletContext);
        }
        if (this.context instanceof ConfigurableWebApplicationContext) {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
            if (!cwac.isActive()) {
                // The context has not yet been refreshed -> provide services such as
                // setting the parent context, setting the application context id, etc
                if (cwac.getParent() == null) {
                    // The context instance was injected without an explicit parent ->
                    // determine parent for root web application context, if any.
                    ApplicationContext parent = loadParentContext(servletContext);
                    cwac.setParent(parent);
                }
                configureAndRefreshWebApplicationContext(cwac, servletContext);
            }
        }
        // 把最先加载的容器设置为根容器(也就是 SpringIOC 容器)放置到servletContext中
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    
        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
        if (ccl == ContextLoader.class.getClassLoader()) {
            currentContext = this.context;
        } else if (ccl != null) {
            currentContextPerThread.put(ccl, this.context);
        }
    
        if (logger.isDebugEnabled()) {
            logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
            WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
        }
        if (logger.isInfoEnabled()) {
            long elapsedTime = System.currentTimeMillis() - startTime;
            logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
        }
    
        return this.context;
    }
    
  • 相关阅读:
    从0开始学习自动化框架Airtest
    测试经理必知必会-Kanban和Scrum区别
    测试工程师的福音-如何使用Sonar完成代码质量检测
    看了很多文章,就这篇说明白了什么是接口测试
    测试经理必知必会:敏捷模型之Kanban
    Selenium元素定位不到?JS注入轻松搞定!
    测试经理必知必会:敏捷开发3355原则
    我知道你会冒泡排序,但是你会优化冒泡排序吗?
    快来使用Portainer让测试环境搭建飞起来吧
    给个MySQL,打算怎么测试?
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/13672359.html
Copyright © 2020-2023  润新知