Spring启动流程解析(总)

2023-05-16

一,Spring启动流程概述

Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段:

  • 容器启动阶段

  • Bean实例化阶段

容器初始化

  1. 加载配置

  2. 分析配置信息

  3. 将Bean信息装配到BeanDefinition

  4. 将Bean信息注册到相应的BeanDefinitionRegistry

  5. 其他后续处理

容器实例化

  1. 根据策略实例化对象

  2. 装配依赖

  3. Bean初始化前处理

  4. 对象初始化

  5. 对象其他处理

  6. 注册回调接口

二,Spring启动流程详解

启动流程源码概览

ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
			throws BeansException {
    super(parent);
    Assert.notNull(paths, "Path array must not be null");
    Assert.notNull(clazz, "Class argument must not be null");
    this.configResources = new Resource[paths.length];
    for (int i = 0; i < paths.length; i++) {
        this.configResources[i] = new ClassPathResource(paths[i], clazz);
    }
    refresh();
}

AbstractApplicationContext

public void refresh() throws BeansException, IllegalStateException {
    // 方法加锁避免多线程同时刷新Spring上下文
    synchronized (this.startupShutdownMonitor) {
        // 准备上下文刷新
        prepareRefresh();

        // 告诉子类刷新内部的beanFactory返回新的BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 在当前上下文中准备要beanFactory
        prepareBeanFactory(beanFactory);

        try {
            // 允许在上下文子类中对beanFactory进行后置处理
            postProcessBeanFactory(beanFactory);

            // 在上下文中将BeanFactory处理器注册为Bean
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册Bean处理器用于拦截Bean的创建
            registerBeanPostProcessors(beanFactory);

            // 在上下文中初始化国际化信息
            initMessageSource();

            // 在上下文中初始化event multicaster(事件多播器)
            initApplicationEventMulticaster();

            // 在指定的上下文子类中初始化其他指定的beans
            onRefresh();

            // 检查并注册事件监听
            registerListeners();

            // 实例化所有剩余的(非延迟初始化)单例
            finishBeanFactoryInitialization(beanFactory);

            // 最后一步:发布相应的事件
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                    "cancelling refresh attempt: " + ex);
            }

            // 如果出现异常则销毁已创建的单例
            destroyBeans();

            // 重置活动标志。
            cancelRefresh(ex);

            // 将异常传递给调用者
            throw ex;
        }
        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

整个refresh()的代码都是同步的,而对应的同步对象是startupShutdownMonitor。startupShutdownMonitor只在refresh()和close()两个方法里被用到,而它是用来同步applicationContext的刷新和销毁。

面试题

Spring的registerShutdownHook和close有什么区别?

close()被调用时会立即关闭或者停止ApplicationContext;而调用registerShutdownHook()将在稍后JVM关闭时关闭或停止ApplicationContext,该方法主要通过JVM ShutdownHook来实现。

ShutdownHook

Java 语言提供一种 ShutdownHook(钩子)机制,当 JVM 接受到系统的关闭通知之后,调用 ShutdownHook 内的方法,用以完成清理操作,从而实现平滑退出应用。

第一步 刷新准备

protected void prepareRefresh() {
    // 设置启动时间。当前毫秒数代表当前applicationContext的创建时间
    this.startupDate = System.currentTimeMillis();
    // 设置容器关闭标志
    this.closed.set(false);
    // 设置启动标志
    this.active.set(true);

    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    // 初始化属性资源
    initPropertySources();

    // 验证所有的属性是否都是可解析的
    getEnvironment().validateRequiredProperties();

    // ApplicationEvent初始化
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

第二步 获取BeanFactory

 

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

该方法对BeanFactory进行刷新。如果刷新前已经存在一个BeanFactory则需要先进行关闭操作,而后初始化一个新BeanFactory。

protected final void refreshBeanFactory() throws BeansException {
    // 判断是否已经存在一个BeanFactory 
    if (hasBeanFactory()) {
        // 销毁已经存在BeanFactory中的所有Bean
        destroyBeans();
        // 关闭BeanFactory
        closeBeanFactory();
    }
    try {
        // 创建新的BeanFactory对象(DefaultListableBeanFactory)
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 给BeanFactory设置Id
        beanFactory.setSerializationId(getId());
        // 该方法主要对2个标志进行设置:allowBeanDefinitionOverriding和allowCircularReferences
        // allowBeanDefinitionOverriding:是否允许使用相同名称重新注册不同的bean(Spring默认true,SpringBoot默认false)
        // allowCircularReferences:是否允许循环依赖
        customizeBeanFactory(beanFactory);
        // 加载配置文件
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            // 新创建的BeanFactory赋给成员变量beanFactory
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

DefaultSingletonBeanRegistry

// 当前这个单例是否正在被销毁
// true:表示单例已经执行了destroy方法,或者出现异常时执行了destroySingleton方法
private boolean singletonsCurrentlyInDestruction = false;

// 缓存两个Bean之间的包含关系。如:一个Bean中包含了一个内部Bean。
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>(16);

// 缓存Bean与其他依赖Bean的关系
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64);

// 缓存被依赖Bean与其他依赖Bean的关系
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64);

// 销毁所有的Bean实例
public void destroySingletons() {
    if (logger.isDebugEnabled()) {
        logger.debug("Destroying singletons in " + this);
    }
    synchronized (this.singletonObjects) {
        // 设置销毁标志
        this.singletonsCurrentlyInDestruction = true;
    }

    // 销毁disposableBeans缓存中所有单例bean
    String[] disposableBeanNames;
    synchronized (this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }
    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
        destroySingleton(disposableBeanNames[i]);
    }

    // 清空包含关系
    this.containedBeanMap.clear();
    // 清空依赖和被依赖关系
    this.dependentBeanMap.clear();
    this.dependenciesForBeanMap.clear();

    // 清空缓存
    clearSingletonCache();
}

加载配置

AbstractXmlApplicationContext

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    // 以Resource方式加载配置
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        // 读取配置文件
        reader.loadBeanDefinitions(configResources);
    }
    // 以String方式加载配置
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        // 读取配置文件
        reader.loadBeanDefinitions(configLocations);
    }
}

AbstractBeanDefinitionReader

@Override
// 通过String数组参数locations加载Bean,并返回加载Bean的数量
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int counter = 0;
    for (String location : locations) {
        // 加载BeanDefinintion
        counter += loadBeanDefinitions(location);
    }
    // 返回加载Bean的数量
    return counter;
}

@Override
// 通过Resource数组参数locations加载Bean,并返回加载Bean的数量
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    for (Resource resource : resources) {
        // 加载BeanDefinintion
        counter += loadBeanDefinitions(resource);
    }
    // 返回加载Bean的数量
    return counter;
}

XmlBeanDefinitionReader

// 从配置文件中加载Bean
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource);
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        // 将Resource资源转化为输入流InputStream
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // 执行加载Bean的过程
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
            "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

// 加载Bean的函数
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {
    try {
        // 加载XML文件,构造XML Document对象
        Document doc = doLoadDocument(inputSource, resource);
        // 注册Bean
        return registerBeanDefinitions(doc, resource);
    }
    // 抛出各种异常
    ......
}

Bean的解析与注册

DefaultBeanDefinitionDocumentReader

// XML配置文件中beans元素
public static final String NESTED_BEANS_ELEMENT = "beans";
// XML配置文件中alias别名元素
public static final String ALIAS_ELEMENT = "alias";
// XML配置文件中name属性
public static final String NAME_ATTRIBUTE = "name";
// XML配置文件中alias属性
public static final String ALIAS_ATTRIBUTE = "alias";
// XML配置文件中import元素
public static final String IMPORT_ELEMENT = "import";
// XML配置文件中resource属性
public static final String RESOURCE_ATTRIBUTE = "resource";
// XML配置文件中profile属性
public static final String PROFILE_ATTRIBUTE = "profile";

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    // 创建Bean解析代理工具类
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        // 解析profile属性
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }

    preProcessXml(root);
    // 解析XML并执行Bean注册
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

    this.delegate = parent;
}

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // root根节点是默认标签
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        // 遍历XML Document的每个节点
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 解析默认标签
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 解析自定义标签
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    // root根节点是自定义标签
    else {
        delegate.parseCustomElement(root);
    }
}

// 解析XML配置文件的节点元素
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // 如果是Import元素
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // 如果是Alias别名元素
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    // 如果是Bean元素
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 如果是嵌套Bean元素(Beans)
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

Import解析

虽然每个单独的XML配置文件都代表体系结构中的逻辑层或模块,但我们可以从多个XML片段中加载Bean定义。如项目中有多个Resource位置,可以使用一个或多个<import />从另外的XML文件中加载Bean定义。

标签用法示例:

<import resource="applicationDao.xml" />
<import resource="applicationService.xml" />

解析标签的源码:

DefaultBeanDefinitionDocumentReader

protected void importBeanDefinitionResource(Element ele) {
    String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
    if (!StringUtils.hasText(location)) {
        getReaderContext().error("Resource location must not be empty", ele);
        return;
    }

    // 解析路径和占位符
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

    // 解析好的资源要放到Set里面
    Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

    // 解析location是相对路径还是绝对路径
    boolean absoluteLocation = false;
    try {
        absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
    }
    catch (URISyntaxException ex) {
        // cannot convert to an URI, considering the location relative
        // unless it is the well-known Spring prefix "classpath*:"
    }

    // 如果是绝对路径
    if (absoluteLocation) {
        try {
            // 直接根据路径加载相应的配置文件
            int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
            }
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error(
                "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
        }
    }
    else {
        try {
            int importCount;
            // 如果是相对路径,则先根据路径得到Resource
            Resource relativeResource = getReaderContext().getResource().createRelative(location);
            // 如果Resource存在
            if (relativeResource.exists()) {
                importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                actualResources.add(relativeResource);
            }
            else {
                // Resource类解析不成功,在classpath路径中去加载。如果没有则抛出异常
                String baseLocation = getReaderContext().getResource().getURL().toString();
                importCount = getReaderContext().getReader().loadBeanDefinitions(
                    StringUtils.applyRelativePath(baseLocation, location), actualResources);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
            }
        }
        catch (IOException ex) {
            getReaderContext().error("Failed to resolve current resource location", ele, ex);
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
                                     ele, ex);
        }
    }
    Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
    getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}

Alias别名注册

每个bean具有一个或多个标识符。这些标识符在承载Bean的容器内必须是唯一的。 Bean通常只有一个标识符,但是如果需要多个标识符,则多余的标识符可以被视为别名。

标签用法示例:

<alias name="dataSource" alias="systemA-dataSource"/>
<alias name="dataSource" alias="systemB-dataSource"/>

在Bean定义中,可以通过使用id属性最多指定的一个名称,同时可以通过name属性中定义任意数量的其他名称来为Bean提供多个名称。但在定义Bean的地方指定所有别名可能并不能满足需求,有时需要在其他地方为Bean定义别名。

解析标签的源码:

SimpleAliasRegistry

// 存放别名的缓存
private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>

// 根据Bean的别名进行注册
public void registerAlias(String name, String alias) {
    Assert.hasText(name, "'name' must not be empty");
    Assert.hasText(alias, "'alias' must not be empty");
    synchronized (this.aliasMap) {
        // 如果别名和名字相同
        if (alias.equals(name)) {
            this.aliasMap.remove(alias);
        }
        else {
            // 如果别名和名字不相同,根据别名获取Bean名称
            String registeredName = this.aliasMap.get(alias);
            if (registeredName != null) {
                // 如果缓存中已经存在该别名,不需要注册到缓存
                if (registeredName.equals(name)) {
                    // An existing alias - no need to re-register
                    return;
                }
                // 如果不允许相同的Bean使用不同的名称则抛出异常
                if (!allowAliasOverriding()) {
                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                                                    name + "': It is already registered for name '" + registeredName + "'.");
                }
            }
            // 对别名进行循环检查
            checkForAliasCircle(name, alias);
            // 把别名放入别名缓存
            this.aliasMap.put(alias, name);
        }
    }
}

// 别名循环检查
public boolean hasAlias(String name, String alias) {
    for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
        // 获取Bean注册名
        String registeredName = entry.getValue();
        // 判断name参数和Bean注册名是否相同
        if (registeredName.equals(name)) {
            // 获取别名
            String registeredAlias = entry.getKey();
            // 判断别名是否相同
            // 递归调用hasAlias
            if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
                return true;
            }
        }
    }
    return false;
}

别名循环检查:A为名称,B为A的别名,需要注册别名<B, A>

  1. 检查B是否有别名,如果没有则返回false

  2. 如果B有别名C,检查C是否与A相同。如果相同返回true,说明有别名循环。如果不相同递归hasAlias(C, B)方法

  3. 如果C无别名,返回false;如果C有别名D且等于A,返回true。如果不相同继续递归hasAlias(D, B)

Bean注册

Spring会自动检测构造型类,并向容器注册相应的BeanDefinition。

DefaultBeanDefinitionDocumentReader

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 解析XML中的BeanDefinition元素
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 注册BeanDefinition
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
        }
        // 发送注册事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

BeanDefinitionParserDelegate

基于单一职责的缘故,BeanDefinitionParserDelegate专门负责解析XML元素的工作,而DefaultBeanDefinitionDocumentReader则主要负责读取XML配置文件的职责。

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // 获取id属性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // 获取name属性
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    // 定义别名list
    List<String> aliases = new ArrayList<String>();
    if (StringUtils.hasLength(nameAttr)) {
        // 因为可以多个别名用,所以解析成别名数组
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }

    // beanName默认为id
    String beanName = id;
    // 如果没有beanName,那么取出别名数组中的第一个作为beanName
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        beanName = aliases.remove(0);
        if (logger.isDebugEnabled()) {
            logger.debug("No XML 'id' specified - using '" + beanName +
                         "' as bean name and " + aliases + " as aliases");
        }
    }

    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }

    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try {
                if (containingBean != null) {
                    // 生成Bean名
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                        beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    // 生成Bean名
                    beanName = this.readerContext.generateBeanName(beanDefinition);
                    String beanClassName = beanDefinition.getBeanClassName();
                    if (beanClassName != null &&
                        beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                        !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                        aliases.add(beanClassName);
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Neither XML 'id' nor 'name' specified - " +
                                 "using generated bean name [" + beanName + "]");
                }
            }
            catch (Exception ex) {
                error(ex.getMessage(), ele);
                return null;
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

// 解析Bean定义不考虑名称或别名。如果在Bean解析过程中产生异常,则返回null
public AbstractBeanDefinition parseBeanDefinitionElement(
    Element ele, String beanName, BeanDefinition containingBean) {

    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    // 解析Bean的class属性
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }

    try {
        String parent = null;
        // 解析parent属性
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        // 为指定的类名和Parent名称创建一个BeanDefinition
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        // 解析Bean元素的属性并应用于Bean
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        // 设置Bean的描述信息
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        // 解析Bean定义的元数据信息(meta以键值对形式存在)
        parseMetaElements(ele, bd);
        // 解析lookup-method元素
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        // 解析replaced-method元素
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

        // 解析构造函数参数
        parseConstructorArgElements(ele, bd);
        // 解析property元素
        parsePropertyElements(ele, bd);
        // 解析qualifier元素
        parseQualifierElements(ele, bd);

        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));

        return bd;
    }
    catch (ClassNotFoundException ex) {
        error("Bean class [" + className + "] not found", ele, ex);
    }
    catch (NoClassDefFoundError err) {
        error("Class that bean class [" + className + "] depends on not found", ele, err);
    }
    catch (Throwable ex) {
        error("Unexpected failure during bean definition parsing", ele, ex);
    }
    finally {
        this.parseState.pop();
    }

    return null;
}

BeanDefinitionReaderUtils

该类的主要职责用于生产新的BeanDefiniti实例,给Bean生成一个名称及调用BeanDefinitionRegistry进行Bean的注册。

public static String generateBeanName(
    BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
    throws BeanDefinitionStoreException {

    String generatedBeanName = definition.getBeanClassName();
    if (generatedBeanName == null) {
        // 如果有父类,名称为:definition.getParentName() + “$child”
        if (definition.getParentName() != null) {
            generatedBeanName = definition.getParentName() + "$child";
        }
        // 如果有指定的工厂类,名称为:definition.getFactoryBeanName() + “$created”
        else if (definition.getFactoryBeanName() != null) {
            generatedBeanName = definition.getFactoryBeanName() + "$created";
        }
    }
    if (!StringUtils.hasText(generatedBeanName)) {
        throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
                                               "'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
    }

    String id = generatedBeanName;
    if (isInnerBean) {
        // 如果是innerBean,名称为
        id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
    }
    else {
        // 如果不是InnerBean则为顶层Bean,使用简单的类名。计数器加1
        int counter = -1;
        while (counter == -1 || registry.containsBeanDefinition(id)) {
            counter++;
            id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
        }
    }
    return id;
}
  • parent

Bean定义可以包含许多配置信息,包括容器相关的信息(比如初始化方法,静态工厂方法等等)以及构造函数参数和属性的值。子Bean可以定义从父Bean定义中继承配置数据,而后它可以根据需要覆盖某些值,或添加其他值。使用父子Bean可以节省很多输入工作。

  • lookup-method

lookup-method注入是容器重写Bean上的方法的一种能力,它可以在容器中根据一个Bean的名字返回查找结果。lookup-method通常涉及Prototype Bean。Spring框架通过使用CGLIB来覆盖该方法的子类以实现lookup-method的注入。该功能可用于在一些可插拔的功能上解除依赖。

  • replace-method

用于在运行时调用使用新的方法替换原有的方法,还能动态的改变原有方法的逻辑。

DefaultListableBeanFactory

// 手动注册的单例名称列表
private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            // 对于AbstractBeanDefinition属性中的methodOverrides校验
            // 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                   "Validation of bean definition failed", ex);
        }
    }

    // 从缓存中根据beanName获取BeanDefinition
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        // 如果BeanDefinition存在并且不允许同名覆盖,则抛出异常
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                   "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                                                   "': There is already [" + existingDefinition + "] bound.");
        }
        // Bean的角色检查
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isWarnEnabled()) {
                logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                            "' with a framework-generated bean definition: replacing [" +
                            existingDefinition + "] with [" + beanDefinition + "]");
            }
        }
        // 如果名字相同,但是BeanDefinition不同打印覆盖日志
        else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isInfoEnabled()) {
                logger.info("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean '" + beanName +
                             "' with an equivalent definition: replacing [" + existingDefinition +
                             "] with [" + beanDefinition + "]");
            }
        }
        // 在缓存中注册Bean
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        // 检查工厂的Bean创建阶段是否已经开始
        if (hasBeanCreationStarted()) {
            // 进入创建阶段,此时无法再修改启动时集合元素(为了稳定迭代)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                // beanName在manualSingletonNames中,说明是手动注册
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {
            // 工厂还未到创建阶段,仍然在注册阶段
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    // 待注册的Bean的已经在beanDefinitionMap缓存中存在,或者已经存在于单例Bean缓存中
    if (existingDefinition != null || containsSingleton(beanName)) {
        // 重置给定Bean的所有BeanDefinition缓存,包括从其派生的Bean的缓存
        resetBeanDefinition(beanName);
    }
}

AbstractBeanFactory

// 保存在至少被创建过一次的beanName
// 如果这个集合中存在beanName,那么说明已经进入了Bean创建阶段
private final Set<String> alreadyCreated =
			Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(256))

第三步 准备BeanFactory

这个阶段主要是当Spring获取了BeanFactory之后,还要做些处理工作(配置工厂的上下文),如:上下文的ClassLoader和BeanPostProcessor。

 

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 内部BeanFactory使用Context上下文的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 配置BeanFactory的Context上下文回调
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // BeanFactory接口不在普通工厂中注册为可解析类型
    // MessageSource 注册(找到并自动装配)为一个Bean
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Register early post-processor for detecting inner beans as ApplicationListeners.
    // 注册早期的后处理器用来将内部Bean检测为ApplicationListeners。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 如果发现LoadTimeWeaver,则准备织入
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // 给类型匹配设置一个临时的ClassLoader
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册默认的environment
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    // 注册systemProperties
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    // 注册systemEnvironment
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

BeanExpressionResolver

通过将值作为表达式进行评估来解析值。它的唯一实现类是StandardBeanExpressionResolver

PropertyEditor

Spring使用PropertyEditor的来实现对象和字符串之间的转换。有时用与对象本身不同的方式表示属性可能更为方便。如:“2019-09-13”字符串形式阅读起来更友好,但也可以将任何方便阅读的日期表现形式转换为日期对象。

Spring提供了很多内置的PropertyEditor,它们都位于org.springframework.beans.propertyeditors包中。默认情况下,大多数由BeanWrapperImpl注册。

描述

ByteArrayPropertyEditor

字节数组属性编辑器。字符串将地转换为相应的字节形式。默认情况下由BeanWrapperImpl注册。

ClassEditor

将表示类的字符串解析为实际类,反之亦然。当找不到类时,将抛出IllegalArgumentException。默认情况下由BeanWrapperImpl注册。

CustomBooleanEditor

布尔属性编辑器。默认情况下由BeanWrapperImpl注册,但是可以通过将其自定义实例注册为自定义编辑器来覆盖。

CustomCollectionEditor

集合属性编辑器,可将任何源集合转换为给定的目标集合类型。

CustomDateEditor

Date自定义属性编辑器,支持自定义DateFormat。

CustomNumberEditor

Number自定义属性编辑器。可用于任何Number子类,如Integer,Long,Float,Double。默认情况下由BeanWrapperImpl注册,但是可以通过将其自定义实例注册为自定义编辑器来覆盖。

FileEditor

将字符串解析为java.io.File对象。默认情况下由BeanWrapperImpl注册。

InputStreamEditor

单向属性编辑器,根据文本字符串生成(通过中间的ResourceEditor和Resource)InputStream,因此InputStream属性可以直接设置为Strings。默认情况下由BeanWrapperImpl注册。请注意,默认用法不会关闭InputStream!

LocaleEditor

将字符串解析为Locale对象,反之亦然(String格式为[country] [variant],与Locale的toString()方法提供的功能相同)。默认情况下由BeanWrapperImpl注册。

PatternEditor

将字符串解析为java.util.regex.Pattern对象,反之亦然。

PropertiesEditor

将字符串转换为Properties对象。默认情况下由BeanWrapperImpl注册。

StringTrimmerEditor

修剪字符串的属性编辑器。 允许将空字符串转换为Null值。

URLEditor

将URL的字符串表示形式解析为实际的URL对象。默认情况下由BeanWrapperImpl注册。

ResourceEditor

资源描述符属性编辑器,可将字符串转换为Resource属性。如:将file:C:/myfile.txt或classpath:myfile.txt转换为Resource属性。 该路径可能包含$ {...}占位符,将被解析为Environment属性,如$ {user.dir}。默认情况下,无法解析的占位符将被忽略。

Aware感知

如果在某个Bean里面想要使用Spring框架提供的功能,可以通过Aware接口来实现。通过实现 Aware 接口,Spring 可以在启动时,调用接口定义的方法,并将 Spring 底层的一些组件注入到自定义的 Bean 中。

描述

ApplicationContextAware

当ApplicationContext创建实现ApplicationContextAware接口的Bean实例时,将为该Bean实例提供对该ApplicationContext的引用。

ApplicationEventPublisherAware

为Bean实例提供对ApplicationEventPublisherAware的引用。

BeanFactoryAware

为Bean实例提供对BeanFactory的引用

BeanNameAware

获取Bean在BeanFactory中配置的名字

MessageSourceAware

为Bean实例提供对MessageSource的引用

EnvironmentAware

获得Environment支持,这样可以获取环境变量

ResourceLoaderAware

获得资源加载器以获得外部资源文件

代码示例

 

public class AwareBean implements ApplicationContextAware, BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("=====>" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx)
            throws BeansException {
        System.out.println("=====>" + ctx.getBean("awareBean"));
    }
}

Xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="awareBean" class="xxx.xxx.aware.AwareBean"/>
</beans>

忽略自动装配

Spring在ConfigurableListableBeanFactory接口中提供了2个可以忽略自动装配的方法:

// 自动装配时忽略指定接口或类的依赖注入
void ignoreDependencyType(Class<?> type);

// 忽略接口实现类中存在依赖外部的Bean注入
void ignoreDependencyInterface(Class<?> ifc);

忽略自动装配的做法使得一些基础组件(如:ApplicationContext或BeanFactory)依赖在自动装配时被忽略,而由框架统一设置依赖。如ApplicationContextAware接口的设置会在ApplicationContextAwareProcessor类中完成。

示例公用xml文件

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="ai.yunxi.TestBean" name="testB1;testB2"/>

    <bean id="human" class="ai.yunxi.autowired.Human"/>
    <bean id="humanService" class="xxx.xxx.autowired.HumanService" autowire="byName"/>
    <!-- 去掉下面的注释,则ignoreDependencyType生效 -->
    <!--<bean class="ai.yunxi.autowired.HumanAutowiringProcessor"/>-->

    <bean id="list" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <value>foo</value>
                <value>bar</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="ignoreImpl" class="xxx.xxx.autowired.IgnoreImpl" autowire="byName" />
    <!-- 去掉下面的注释,则ignoreDependencyInterface生效 -->
    <!--<bean class="xxx.xxx.autowired.InterfaceIgnoreProcessor"/>-->
</beans>

ignoreDependencyType

public class Human {
    private String name;

    public Human( String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

实现了BeanFactoryPostProcessor的忽略自动装配处理器,这里是忽略的类。

public class HumanAutowiringProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        
        beanFactory.ignoreDependencyType(Human.class);
    }
}

ignoreDependencyInterface

接口类

public interface IgnoreInterface {
    void setList(List<String> list);
}

实现类

public class IgnoreImpl implements IgnoreInterface {

    private List<String> list;

    @Override
    public void setList(List<String> list) {
        this.list = list;
        System.out.println("ok.......");
    }

    public List<String> getList() {
        return list;
    }
}

实现了BeanFactoryPostProcessor的忽略自动装配处理器,这里忽略的是接口。

public class InterfaceIgnoreProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        beanFactory.ignoreDependencyInterface(IgnoreInterface.class);
    }
}

BeanPostProcessor

如果想在Spring容器中完成Bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理,就需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。

第四步 BeanFactory后处理

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // ServletContextAwareProcessor中拿到应用上下文持有的servletContext引用和servletConfig引用
    // 添加ServletContextAwareProcessor后处理器
    beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
    
    // 在自动注入时忽略指定的依赖接口
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

    // 向WebApplicationContext使用的BeanFactory注册Web相关作用域对象
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    
    // 注册和Environment有关的beans
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

WebApplicationContextUtils

该类位于包`org.springframework.web.context.support`是一个使检索指定ServletContext的根WebApplicationContext的便捷工具类。它如下工具方法:

  1. 在Web容器启动过程中注册Web相关作用域Bean(request/session/globalSession/application)

  2. 在Web容器启动过程中注册相应类型的工厂Bean ,依赖注入的Bean时能访问到正确的对象(ServletRequest/ServletResponse/HttpSession/WebRequest)

  3. 在Web容器启动过程中注册Web相关环境Bean

  4. 在Web容器启动过程中初始化Servlet propertySources

  5. 在客户化Web视图或者MVC action中,使用该工具类可以很方便地在程序中访问Spring应用上下文(application context)。

自定义作用域

Scope也称作用域,在Soring Ioc容器指其创建的Bean对象对其他Bean对象的请求可见范围,是用来声明IoC容器中的对象应该处的限定场景或者说该对象的存活空间,即在IOC容器在对象进入相应的Scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。

诸如WebApplicationContext之类的ApplicationContext可以注册相对于标准作用域(Singleton/Prototype)的特定环境Scope作用域,例如:“request”和“session”作用域。

Bean的Scope作用域范围同样是可扩展的:即可以定义自己的范围,甚至重新定义现有范围,但不能覆盖内置的Singleton和Prototype范围。

// 从scope中根据名字返回对象
Object get(String name, ObjectFactory objectFactory);

// 从Scope中删除该对象
Object remove(String name);

// 注册的Scope被销毁或Scope中的指定对象被销毁时执行回调
void registerDestructionCallback(String name, Runnable destructionCallback);

// 获取Scope的会话标识符
String getConversationId(); 

ConfigurableBeanFactory接口中允许使用自定义的作用域范围扩展BeanFactory的标准作用域“ Singleton”和“ Prototype”,并为新的作用域范围进行注册。在编写好自定义Scope之后,需要让Spring容器识别新的Scope作用域。

代码方式注册

以下方法是在Spring容器中注册新Scope的主要方法,该方法在ConfigurableBeanFactory接口中定义:

// 第一个参数是与该Scope的全局唯一名称。在Spring容器中,此名称是Singleton和Prototype
// 第二个参数是希望注册和使用的自定义Scope实例
void registerScope(String scopeName, Scope scope);

如果已经写好了自己的自定义`Scope`实现,并且已经将其进行了注册:

Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);

然后就可以在配置文件中创建与自定义`Scope`规则对应的Bean定义:

<bean id="..." class="..." scope="thread"/>

配置方式注册

对于ApplicationContext来说,因为它可以自动识别并加载BeanFactoryPostProcessor,所以我们就可以直接在配置文件中,通过这个CustomScopeConfigurer注册来使新的Scope作用域范围生效

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="customerScope" value="xxx.xxx.scope.CustomerScope"/>
            </map>
        </property>
    </bean>-->

    <bean id="human" class="xxx.xxx.autowired.Human" scope="customerScope">
        <!-- 让Bean符合自定义的作用域 -->
        <!--<aop:scoped-proxy/>-->
    </bean>
</beans>

测试类

public class TestScope {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx =
                new ClassPathXmlApplicationContext("scope.xml");

        // 代码方式注册新的Scope作用域
        // ctx.getBeanFactory().registerScope("customerScope", new CustomerScope());

        System.out.println(ctx.getBeanFactory().getBeanDefinition("human").getScope());
        String scopes[] = ctx.getBeanFactory().getRegisteredScopeNames();
        for (String scope : scopes) {
            System.out.println(scope);
        }
    }
}

第五步 调用后处理器

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

BeanFactoryPostProcessor

BeanFactoryPostProcessor接口与BeanPostProcessor相似,但有一个主要区别:BeanFactoryPostProcessor用来操作Bean的配置元数据。也就是说,Spring IoC容器允许BeanFactoryPostProcessor读取配置元数据,并能在容器实例化任何Bean之前更改这些元数据。换句话说 :就是可以让我们随心所欲地修改BeanFactory内所有BeanDefinition定义数据。

BeanDefinitionRegistryPostProcessor 是对标准BeanFactoryPostProcessor的扩展,允许在进行常规BeanFactoryPostProcessor检测之前注册其他Bean定义。特别是,BeanDefinitionRegistryPostProcessor注册的Bean定义又定义了BeanFactoryPostProcessor实例。

使用示例

Xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="xxx.xxx.processor.Car">
        <property name="name" value="benz"/>
    </bean>

    <bean id="carBeanFactoryPostProcessor1"
          class="xxx.xxx.processor.CarBeanFactoryPostProcessor1">
        <property name="order" value="0" />
    </bean>

    <bean id="carBeanFactoryPostProcessor2"
          class="xxx.xxx.processor.CarBeanFactoryPostProcessor2">
        <property name="order" value="1" />
    </bean>
</beans>

自定义BeanFactoryPostProcessor

// 1号后置处理器
public class CarBeanFactoryPostProcessor1 implements BeanFactoryPostProcessor, Ordered {
    int order;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        System.out.println("=======> 执行CarBeanFactoryPostProcessor1");
        BeanDefinition bd = beanFactory.getBeanDefinition("car");
        bd.getPropertyValues().addPropertyValue("name", "bmw");
    }

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public int getOrder() {
        return order;
    }
}

// 2号后置处理器
public class CarBeanFactoryPostProcessor2 implements BeanFactoryPostProcessor, Ordered {
    int order;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        System.out.println("=======> 执行CarBeanFactoryPostProcessor2");
        BeanDefinition bd = beanFactory.getBeanDefinition("car");
        bd.getPropertyValues().addPropertyValue("color", "red");
    }

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public int getOrder() {
        return order;
    }
}

// 实现BeanDefinitionRegistryPostProcessor接口的后处理器类
public class MobileBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("=======> 执行MobileBeanFactoryPostProcessor_1");
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Mobile.class);
        registry.registerBeanDefinition("mobile", beanDefinitionBuilder.getBeanDefinition());
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("=======> 执行MobileBeanFactoryPostProcessor_2");
        BeanDefinition bd = beanFactory.getBeanDefinition("mobile");
        bd.getPropertyValues().addPropertyValue("number", "123");
    }
}

可以在项目中配置多个BeanFactoryPostProcessor,同时通过设置Order属性来控制这些BeanFactoryPostProcessor的执行顺序,当然仅当BeanFactoryPostProcessor实现Ordered接口时,才可以设置此属性。

Spring排序接口

Spring框架中有很多实现了相同接口的类,那么这些实现类之间必定会有优先级的问题。Spring提供了Ordered接口来处理相同接口实现类的优先级问题。Ordered接口,顾名思义,就是用来排序的。

流程源码分析

源码流程

源码解析

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // 临时缓存,用来记录已经调用过的BeanFactoryPostProcessor
    Set<String> processedBeans = new HashSet<String>();

    // 如果BeanFactory实现了BeanDefinitionRegistry接口
    // 从类图上可以看到其实是指DefaultListableBeanFactory或者GenericApplicationContext
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // 存放普通BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
        // 存放BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();

        // 循环applicationContext中已经注册的BeanFactoryPostProcessor
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // 如果是实现了BeanDefinitionRegistryPostProcessor的后处理器
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                    (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 执行postProcessBeanDefinitionRegistry回调
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 把该后处理器加入到registryProcessors
                registryProcessors.add(registryProcessor);
            }
            else {
                // 否则就是普通的后处理器
                regularPostProcessors.add(postProcessor);
            }
        }

        // 在这里先不初始化FactoryBeans,因为需要保留这些Beans让BeanFactoryPostProcessor进行处理
        // BeanDefinitionRegistryPostProcessor将按照PriorityOrdered,Ordered进行分类
        
        // 临时缓存,用来记录待执行回调方法的BeanFactoryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

        // 首先,处理实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
        String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 保存到待执行BeanFactoryPostProcess回调的缓存
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // 保存到已经执行过BeanFactoryPostProcess回调的缓存
                processedBeans.add(ppName);
            }
        }
        // 对待执行缓存进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 执行BeanFactoryPostProcess的回调函数
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // 清空待执行BeanFactoryPostProcess回调的缓存
        currentRegistryProcessors.clear();

        // 其次,再处理实现了Ordered接口的BeanDefinitionRegistryPostProcessor
        Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                // 保存到待执行BeanFactoryPostProcess回调的缓存
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // 保存到已经执行过BeanFactoryPostProcess回调的缓存
                processedBeans.add(ppName);
            }
        }
        // 对待执行缓存进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 执行BeanFactoryPostProcess的回调函数
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // 清空待执行BeanFactoryPostProcess回调的缓存
        currentRegistryProcessors.clear();

        // 最后,处理所有其他BeanDefinitionRegistryPostProcessor
        boolean reiterate = true;
        // 循环处理其他BeanDefinitionRegistryPostProcessor
        while (reiterate) {
            reiterate = false;
            // 把所有实现BeanDefinitionRegistryPostProcessor的类名取出来
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            // 遍历postProcessorNames
            for (String ppName : postProcessorNames) {
                // 已经处理过的缓存不包含该类名
                if (!processedBeans.contains(ppName)) {
                    // 保存到待执行BeanFactoryPostProcess回调的缓存
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    // 保存到已经执行过BeanFactoryPostProcess回调的缓存
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            // 对待执行缓存进行排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            // 执行BeanFactoryPostProcess的回调函数
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 清空待执行BeanFactoryPostProcess回调的缓存
            currentRegistryProcessors.clear();
        }

        // 处理所有处理器,并执行postProcessBeanFactory回调
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }
    else {
        // 调用在上下文中注册的工厂处理器
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 在这里不初始化FactoryBeans,因为需要让BeanFactoryPostProcessor来进行处理
    // 获取所有实现了BeanFactoryPostProcessor接口的类名称
    String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // 实现了PriorityOrdered接口的PostProcessor缓存
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    // 实现了Ordered接口的PostProcessor缓存
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 没有实现任何Order接口的PostProcessor缓存
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // 遍历postProcessorNames开始处理BeanFactoryPostProcessor
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // 如果包含,代表在上面的代码已经处理过则跳过
        }
        // 首先,处理实现了PriorityOrdered接口的BeanFactoryPostProcessor
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        // 其次,处理实现了Ordered接口的BeanFactoryPostProcessor
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        // 最后,处理没有实现任何Order接口接口的BeanFactoryPostProcessor
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 首先,处理实现了PriorityOrdered接口的BeanFactoryPostProcessor
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // // 其次,再处理实现了Ordered接口的BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // // 最后,处理所有其他BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 清除被缓存的BeanDefinition,因为后处理器可能已经修改了原始元数据,例如:替换占位符
    beanFactory.clearMetadataCache();
}

第六步 注册后处理器

// 实例化并且注册所有BeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

BeanPostProcessor

BeanPostProcessor是Spring的Bean工厂中一个非常重要的接口,允许Spring框架在新创建Bean实例时对其进行定制化修改。比如我们对Bean内容进行修改、创建代理对象等等。也就是说,Spring IoC容器实例化了一个Bean,而后BeanPostProcessor开始完成它们的工作。

BeanPostProcessor接口定义了回调方法,可以实现这些方法,以提供自己的实例化逻辑(或覆盖容器的默认值),依赖关系解析逻辑等。如果您想在Spring容器完成Bean的实例化、配置和初始化之后实现一些自定义逻辑,则可以插入一个或多个自定义BeanPostProcessor实现。

public interface BeanPostProcessor {
    // Bean初始化之前调用
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    
    // Bean初始化之后调用
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

在实际使用中可以配置多个BeanPostProcessor实例,并且可以通过设置Order属性来控制这些BeanPostProcessor的执行顺序。只有当BeanPostProcessor实现Ordered接口时,才可以设置此属性。

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor实际上继承了BeanPostProcessor接口,主要作用于实例化阶段的前后。

使用方式

public class CarBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("===> 1.调用postProcessBeforeInitialization()");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("===> 1.调用postProcessAfterInitialization()");
        return bean;
    }
}

public class CarInstantiationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
            throws BeansException {
        System.out.println("===> 2.调用postProcessBeforeInstantiation()");
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName)
            throws BeansException {
        System.out.println("===> 2.调用postProcessAfterInstantiation()");
        return false;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out.println("===> 2.调用postProcessPropertyValues()");
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("===> 2.调用postProcessBeforeInitialization()");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("===> 2.调用postProcessAfterInitialization()");
        return bean;
    }
}

Xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="xxx.xxx.processor.Car">
        <property name="name" value="benz"/>
    </bean>

    <bean id="testPostProcessor"
          class="xxx.xxx.processor.CarBeanPostProcessor"/>

    <bean id="testInstantiationBeanPostProcessor"
          class="xxx.xxx.processor.CarInstantiationBeanPostProcessor"/>
</beans>

源码解读

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // 从BeanFactory中获取所有BeanPostProcessor的名字
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // 注册BeanPostProcessorChecker,以便在BeanPostProcessor实例化期间创建一个Bean时记录一条info消息
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 对BeanPostProcessor按照实现的接口PriorityOrdered,Ordered进行分类并存储
    // 保存实现PriorityOrdered接口的BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    // 保存实现Ordered接口的BeanPostProcessor
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 保存没有实现PriorityOrdered和Ordered接口的BeanPostProcessor
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // 遍历postProcessorNames所有的BeanPostProcessor
    for (String ppName : postProcessorNames) {
        // 如果调用适配函数,发现该类实现了PriorityOrdered接口
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 从容器中取出BeanPostProcessor
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            // 保存到List集合中
            priorityOrderedPostProcessors.add(pp);
            // 如果这个类实现了MergedBeanDefinitionPostProcessor接口
            if (pp instanceof MergedBeanDefinitionPostProcessor接口) {
                internalPostProcessors.add(pp);
            }
        }
        // 如果调用适配函数,发现该类实现了Ordered接口
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        // 既没有实现PriorityOrdered接口也没有实现Ordered接口
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 首先,处理实现PriorityOrdered接口的BeanPostProcessor
    // 对BeanPostProcessor进行排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 注册BeanPostProcessor
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 其次,处理实现Ordered接口的BeanPostProcessor
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    // 对BeanPostProcessor进行排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 注册BeanPostProcessor
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 处理其他普通的BeanPostProcessor
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 对BeanPostProcessor进行排序.
    sortPostProcessors(internalPostProcessors, beanFactory);
    // 注册BeanPostProcessor
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // 重新注册后BeanPostProcessor,用于内部Bean检测为ApplicationListener,//将其移至处理器链的末尾(用于拾取代理等)
    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

Bean的类型

Spring中有两种类型的Bean:

  • 普通Bean

  • 工厂Bean(即:FactoryBean)

FactoryBean

普通Bean可以直接使用Xml进行配置,但如果你的Bean拥有复杂的初始化代码(如涉及到很多其他的Bean),使用XML配置方式比较困难,这时就可以使用FactoryBean,并在该类中编写复杂的初始化,然后将自定义FactoryBean插入容器。

FactoryBean接口提供了三种方法:

T getObject() throws Exception;   // 返回此工厂创建的对象实例
Class<?> getObjectType();         // 返回的对象类型,如果对象类型未知则返回null
boolean isSingleton();            // 如果FactoryBean返回单例返回true,否则返回false。

这个接口使你可以提供一个复杂的逻辑来生成Bean。它本质是一个Bean,但这个Bean不是用来注入到其它地方像Service、Dao一样使用的,它是用来生成其它Bean使用的。

Spring框架中的许多地方都使用了FactoryBean概念和接口,Spring附带了50多个FactoryBean接口实现。很多开源项目在集成Spring 时也都使用到FactoryBean,比如 MyBatis3 提供 mybatis-spring项目中的 org.mybatis.spring.SqlSessionFactoryBean。

FactoryBean使用示例:

PersonFactoryBean

public class PersonFactoryBean implements FactoryBean<Person> {

    private String jsonInfo;

    @Override
    public Person getObject() throws Exception {
        ObjectMapper om = new ObjectMapper();
        return om.readValue(jsonInfo, Person.class);
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    public String getJsonInfo() {
        return jsonInfo;
    }

    public void setJsonInfo(String jsonInfo) {
        this.jsonInfo = jsonInfo;
    }
}

beans.xml

<bean id="person" class="xxx.xxx.PersonFactoryBean">
    <property name="jsonInfo"
              value="{ &quot;id&quot;: 1,&quot;name&quot;: &quot;abc&quot;,
                     &quot;age&quot;: 27, &quot;salary&quot;: 5555.0,
                     &quot;address&quot;: &quot;beijing&quot;}"/>
</bean>

Bean生命周期

Spring Bean的生命周期只有四个阶段:

  1. 实例化(Instantiation):调用构造函数

  2. 属性赋值(Populate):设置依赖注入

  3. 初始化(Initialization):调用init方法

  4. 销毁(Destruction):调用destory方法

生命周期也可以理解为四个等级。每个等级中都用有相应的接口,实现其中某个接口或者将实现类注入到Spring容器,容器就会在相应的时机调用其方法。

  1. 工厂级处理器接口

  2. 容器级生命周期接口

  3. Bean级生命周期接口

  4. Bean本身方法

接口

分类

描述

BeanFactoryPostProcessor

工厂后处理器接口

容器创建完毕,装配Bean源后立即调用

InstantiationAwareBeanPostProcessor

容器后处理器接口

分别在调用构造之前,注入属性之前,实例化完成时调用

BeanPostProcessor

容器后处理器接口

分别在Bean的初始化方法调用前后执行

BeanNameAware

Bean级后置处理器接口

注入属性后调用

BeanFactoryAware

Bean级后置处理器接口

注入属性后调用

InitializingBean

Bean级后置处理器接口

在类本身的初始化方法之前调用其方法(本身也是初始化方法)

DisposableBean

Bean级后置处理器接口

在类本身的销毁方法执行之前调用其方法(本身也是销毁方法)

init方法

Bean本身方法

在注入属性之后调用初始化方法

destroy方法

Bean本身方法

在关闭容器的时候进行销毁

Spring中Bean初始化/销毁的三种方法

  1. 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法;

  2. 在<bean> 元素上添加 init-method/destroy-method来指定初始化之后 /销毁之前调用的操作方法;

  3. 在方法上加上@PostConstruct 或@PreDestroy注解来指定该方法是在初始化之后还是销毁之前调用。

 

public class Person implements InitializingBean {
    private int id;
    private String name;
    private int age;
    private BigDecimal salary;
    private String address;

    public Person() {
        System.out.println("Person构造函数");
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public BigDecimal getSalary() {
        return salary;
    }

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @PostConstruct
    public void postConstruct(){
        System.out.println("调用PostConstruct");
    }

    public void initMethod(){
        System.out.println("调用initMethod");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用afterPropertiesSet()");
    }
}

Spring Bean的生命周期:

  1. Spring对Bean进行实例化,调用Bean的构造参数

  2. 设置对象属性,调用Bean的set方法,将属性注入到bean的属性中

  3. 检查Bean是否实现BeanNameAware、BeanFactoryAware、ApplicationContextAware接口,如果实现了这几个接口Spring会分别调用其中实现的方法。

  4. 如果Bean是否实现BeanPostProcessor接口,Spring会在初始化方法的前后分别调用postProcessBeforeInitialization和postProcessAfterInitialization方法

  5. 如果Bean是否实现InitalizingBean接口,将调用afterPropertiesSet()方法

  6. 如果Bean声明初始化方法,也会被调用

  7. 使用Bean。Bean将会一直保留在应用的上下文中,直到该应用上下文被销毁。

  8. 检查Bean是否实现DisposableBean接口,Spring会调用它们的destory方法

  9. 如果Bean声明销毁方法,该方法也会被调用

Bean获取

org.springframework.beans.factory.support.AbstractBeanFactory

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

    // 将别名解析为规范Bean名称,如果是FactoryBean还需删除前缀
    final String beanName = transformedBeanName(name);
    Object bean;

    // 检查缓存是否有对象
    // 循环依赖解决的关键入口
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            // 该Bean是否正在创建中
            if (isSingletonCurrentlyInCreation(beanName)) {
                // logger.debug(.....) 打印日志(略)
            }
            else {
                // logger.debug(.....) 打印日志(略)
            }
        }
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 如果已经创建了Bean实例则抛出异常,因为可能在循环引用中
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 检查工厂中是否存在Bean定义
        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 {
            // 合并BeanDefinition。合并主要是因为BeanDefinition可能存在parent BeanDefinition
            // 所以要依据合并后的BeanDefinition来实例化和初始化
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 检查合并后的BeanDefinition。主要是检查是否是abstract
            checkMergedBeanDefinition(mbd, beanName, args);

            // 获取依赖信息
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                // 确保当前Bean依赖的Bean初始化
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        // throw异常(略)
                    }

                    try {
                        // 注册依赖Bean
                        registerDependentBean(dep, beanName);
                        // 获取依赖Bean
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        // throw异常(略)
                    }
                }
            }

            // 创建Bean实例
            // 如果是单例对象
            if (mbd.isSingleton()) {
                // 使用匿名对象工厂来创建Bean
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            // 创建Bean
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // 从单例缓存中显式删除实例。在创建过程可能将它提前引用缓存中,以方便循环引用解析。
                            // 还要删除所有对该Bean临时引用的Bean
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
	    // 如果是Prototype对象
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    // 记录到当前创建的原型对象缓存
                    beforePrototypeCreation(beanName);
                    // 创建Bean
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // 创建完毕,从当前创建的原型对象缓存移除
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            // 既不是Singleton也不是Prototype,可能是自定义scope的对象
            else {
                // 获取Scope名称
                String scopeName = mbd.getScope();
                // 根据名称解析出对应的Scope对象
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            // 记录到当前创建的原型对象缓存
                            beforePrototypeCreation(beanName);
                            try {
                                // 创建Bean
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                // 创建完毕,从当前创建的原型对象缓存移除
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    // throw异常(略)
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 所需的类型与实际Bean实例类型进行匹配转换
    if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
        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;
}

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

// 根据Bean注册名称返回单例对象,检查已经实例化的单例,并允许提前曝光当前创建的单例对象(解析循环引用)
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 != NULL_OBJECT ? singletonObject : null);
}

// 根据Bean注册名称返回单例对象。如果尚未注册,则创建并注册一个新的
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "'beanName' must not be null");
    // 注意synchronized
    synchronized (this.singletonObjects) {
        // 根据Bean名称从单例缓存中获取实例
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
                // 抛出异常。原因:工厂单例销毁时不允许创建Bean实例
                // throw new BeanCreationNotAllowedException(.......);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
            // 创建前检查,主要检查两项。如果不成功抛出异常
            // 1. 正在创建缓存inCreationCheckExclusions中不包含该Bean
            // 2. 待创建缓存singletonsCurrentlyInCreation中可以添加该Bean
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<Exception>();
            }
            try {
                // 从工厂中获取单例对象
                singletonObject = singletonFactory.getObject();
                // 创建成功则为true
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // 如果出现异常,则从单例缓存中获取
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // 创建后检查,仍然是两项检查:
                // 1. 正在创建缓存inCreationCheckExclusions中不包含该Bean
                // 2. 待创建缓存singletonsCurrentlyInCreation中可以移除该Bean
                afterSingletonCreation(beanName);
            }
            // 创建成功同步几个重要的缓存
            if (newSingleton) {
                // 同步缓存:
                // 1. singletonObjects中添加单例对象
                // 2. singletonFactories移除该Bean
                // 3. earlySingletonObjects移除该Bean
                // 4. registeredSingletons添加该BeanName
                addSingleton(beanName, singletonObject);
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

Bean创建

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

// 创建实例,填充实例,应用后处理器
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean '" + beanName + "'");
    }
    // 合并的BeanDefinition
    RootBeanDefinition mbdToUse = mbd;

    // 确保解析并加载Bean的Class
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    // 如果解析的类在合并的BeanDefinition不存在,则克隆Bean定义
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        // 设置Bean的Class
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        // Spring将lookup-method和replace-method统称为override method,这里主要就是处理这2个函数
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                                               beanName, "Validation of method overrides failed", ex);
    }

    try {
        // 该函数的作用是给 BeanPostProcessors 后置处理器返回一个代理对象的机会
        // 这里是实现AOP处理的重要地方
        // AOP是通过BeanPostProcessor机制实现的,而接口InstantiationAwareBeanPostProcessor是实现代理的重点
        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);
    }

    // 如果后处理器返回的Bean为空,则调用doCreateBean执行创建Bean的过程
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}

// 实际创建指定的Bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

    // BeanWrapper 是一个用于包装Bean实例的接口,通过这个接口可以设置/获取Bean实例的属性
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 从未完成的实例缓存中获取
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // 如果缓存中不存在,则执行创建(三种方式)
    if (instanceWrapper == null) {
        // 创建 bean 实例,并将实例封装在BeanWrapper中返回。createBeanInstance中包含三种创建方式:
        // 1.工厂方法创建Bean实例
        // 2.通过构造方法自动注入(autowire by constructor)的方式创建
        // 3.通过无参构造方法方法创建
        // 如果Bean配置了lookup-method和replace-method,则使用CGLIB增强Bean实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 获取包装的Bean实例
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    // 获取包装的Class
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    // 待解析的目标类型
    mbd.resolvedTargetType = beanType;

    // 允许BeanPostProcessor修改合并的BeanDefinition。这里主要是合并Bean的定义信息
    // Autowired等注解就是在这一步完成预解析,并且将注解需要的信息放入缓存
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 应用MergedBeanDefinitionPostProcessor后处理器
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // earlySingletonExposure 是一个重要的变量,用于表示是否提前暴露单例Bean,用于解决循环依赖。
    // earlySingletonExposure 由三个条件组成:是否是单例、是否允许循环引用、当前Bean是否处于创建的状态中
    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");
        }
        // 避免循环依赖,在Bean初始化完成前添加ObjectFactory到singletonFactories缓存。
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                // 此回调使后处理器有机会提前曝光Bean(即在目标Bean完全初始化之前)。通常是为了解决循环依赖
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // 下面是初始化Bean的流程
    Object exposedObject = bean;
    try {
        // 使用BeanDefinintion的属性值填充Bean实例
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // 初始化Bean
            // 如果Bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口则设置
            // 应用BeanPostProcessor后处理器
            // 执行自定义init-method方法
            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缓存中查询,目的是验证是否存在循环依赖
	// 如果存在循环依赖,在这里earlySingletonReference不为空
        Object earlySingletonReference = getSingleton(beanName, false);
        // 在检测到循环依赖的情况下,earlySingletonReference不会为null
        if (earlySingletonReference != null) {
            // 如果exposedObject没有在initializeBean初始化方法中被改变,说明没有被增强
            // 初始化之后的Bean等于原始的bean说明不是proxy对象
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 确定是否已经给指定的beanName称注册了依赖
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // Bean创建后其依赖的Bean一定也是已经创建的
                // 如果actualDependentBeans不为空,则表示依赖的Bean并没有被创建完,即存在循环依赖
                if (!actualDependentBeans.isEmpty()) {
                    // 抛出异常
                    // throw new BeanCurrentlyInCreationException(....)
                }
            }
        }    }

    // Register bean as disposable.
    // 如果Bean实现了Disposable,则注册该Bean为
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

// 创建Bean实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        // 抛出异常
        // throw new BeanCreationException(.....);
    }

    // 如果工厂方法不为空
    if (mbd.getFactoryMethodName() != null) {
        // 使用工厂方法创建实例
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 调用实例化策略接口来实例化Bean,这里使用无参构造
    return instantiateBean(beanName, mbd);
}

// 实例化Bean
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
            }, getAccessControlContext());
        }
        else {
            // InstantiationStrategy负责进行实例化
            // SimpleInstantiationStrategy是一个简单的用于Bean实例化的类。如:由Bean类的默认构造函数、带参构造函数或者工厂方法等来实例化Bean。不支持方法注入。
            // CglibSubclassingInstantiationStrategy如果方法需要被覆盖来实现“方法注入”,使用CGLIB动态生成子类
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        // 实例化后的Bean使用BeanWrapper包装。BeanWrapper可以设置以及访问被包装对象的属性值
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        // 初始化BeanWrapper包装包含了2个工作:设置ConversionService和CustomerEditor
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

// 初始化Bean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        // 设置Aware
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 调用初始化前处理器
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 执行自定义初始化方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 调用初始化后处理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

解决循环引用

 

// 注册名称返回单例对象,检查已经实例化的单例,并允许提前引用当前创建的单例对象(解析循环引用)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从单例缓存中根据Bean名字获取单例对象
    Object singletonObject = this.singletonObjects.get(beanName);
    // 如果单例对象为空,并且单例对象正在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 注意synchronized关键字
        synchronized (this.singletonObjects) {
            // 从earlySingletonObjects缓存中通过Bean名称获取对象
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 如果单例对象仍然为空,并且允许提前引用为true
            // allowEarlyReference参数含义:是否允许提前曝光
            if (singletonObject == null && allowEarlyReference) {
                // 从singletonFactories中根据Bean名称获取对应的单例工厂
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 通过工厂创建单例对象(此时还未进行依赖注入)
                    singletonObject = singletonFactory.getObject();
                    // 把创建的单例对象放到提前引用的缓存
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // 移除该单例对象的工厂
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
}

代码中出现的缓存:

  1. singletonObjects:初始化完成的单例对象缓存;

  2. earlySingletonObjects:提前曝光的单例对象缓存;

  3. singletonFactories:单例Bean的工厂函数对象缓存;

  4. singletonsCurrentlyInCreation:即将创建的单例集合

第七步 初始化消息源

Spring中定义一个MessageSource接口,以用于支持信息的国际化和包含参数的信息的替换。ApplicationContext接口扩展了MessageSource接口,因而提供了消息处理的功能(i18n或者国际化)。与HierarchicalMessageSource一起使用,还能够处理嵌套的消息,这些是Spring提供的处理消息的基本接口。

public interface MessageSource {
    // 用来从MessageSource获取消息的基本方法。如果在指定的locale中没有找到消息,则使用默认的消息
    // args中的参数将使用标准类库中的MessageFormat来替换消息中的值
    String getMessage(String code, Object[] args, String default, Locale loc):

    // 与上一个方法相同,不同之处在于:没有指定默认值。如果没找到消息,会抛出一个NoSuchMessageException异常。
    String getMessage(String code, Object[] args, Locale loc) throws NoSuchMessageException;

    // 与上面的方法不同之处在于:将code、args等属性封装到MessageSourceResolvable中
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}

MessageSource类图

Spring提供了两个MessageSource实现:ResourceBundleMessageSource和StaticMessageSource。它们都继承HierarchicalMessageSource能够处理嵌套的消息。

ResourceBundleMessageSource会用得更多一些。StaticMessageSource很少被使用,但能以编程的方式向源添加消息。

类或接口

描述

HierarchicalMessageSource

MessageSource子接口,提供解析层级消息的能力。该接口的目的是设置父MessageSource用于当前对象无法解析消息时,由父MessageSource尝试解析。

DelegatingMessageSource

空的MessageSource,它将所有处理转发给父MessageSource。如果没有父MessageSource,它不会处理任何消息。用户未指定MessageSource时,Spring默认使用该类。该类的功能比较简单:将字符串和参数数组格式化为一个消息字符串

AbstractMessageSource

支持“配置文件”方式的抽象类,内部提供一个与区域设置无关的公共消息配置文件,消息代码为关键字

AbstractResourceBasedMessageSource

基于资源并实现了MessageSource接口的抽象类,同时提供了一些参数配置的方法

ResourceBundleMessageSource

该类通过beanName指定一个资源名(包括类路径的全限定资源名),或通过beanNames指定一组资源名。不同的区域获取加载资源文件,达到国际化信息的目的。该类依赖JDK的ResourceBundle,并结合了JDK MessageFormat提供的标准消息解析。被访问的ResourceBundle和为每个消息生成的MessageFormat都会被缓存。

ReloadableResourceBundleMessageSource

同ResourceBundleMessageSource。该类参与Spring ApplicationContex的资源加载。它使用java.util.Properties作为其消息的自定义数据结构,通过PropertiesPersister策略从Spring Resource中加载它们。该策略不仅能够根据时间戳的更改重新加载文件,而且还能够使用特定的字符编码加载属性文件。

StaticMessageSource

MessageSource的简单实现,允许以编程方式注册消息,提供基本的国际化支持(通常用于测试)

使用示例

Xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
​
    <bean id="messageSource"
          class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>locale.messages</value>
                <value>locale.exceptions</value>
            </list>
        </property>
    </bean>
​
</beans>

messageSource配置

# exceptions_en_US.properties文件
exceptions.illegal = The user {0} attempted to login, time: {1}
​
# exceptions_zh_CN.properties文件
exceptions.illegal = \u975e\u6cd5\u7528\u6237{0}\u5c1d\u8bd5\u767b\u5f55, \u65f6\u95f4\uff1a{1}
​
# message_en_US.properties文件
id.ilegal = userid {0} is illegal! time: {1}
password.empty = username{0}'s password is empty!
​
# message_zh_CN.properties文件
id.ilegal = \u7528\u6237\u7f16\u53f7{0}\u975e\u6cd5\u767b\u5f55\uff01{1}
password.empty = \u7528\u6237\u540d{0}\u7684\u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a\uff01

注意:中文messageSource文件需要把中文转为Ascii

源码解读

getMessage()时序图

 

该段源码主要目的

当一个ApplicationContext被加载时,它会自动在context中查找已定义为MessageSource类型的Bean。此Bean的名称须为messageSource。

如果找到,那么所有对上述方法的调用将被委托给该Bean。否则ApplicationContext会在其父类中查找是否含有同名的Bean。如果有,就把它作为MessageSource。如果最终没有找到任何的消息源,实例化一个空的DelegatingMessageSource,使它能够接受上述方法的调用。

protected void initMessageSource() {
    // 获取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    // beanFactory中是否包含名字为messageSource的Bean
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        // 创建MessageSource类型的Bean
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // 判断messageSource是否有parent MessageSource
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            // 设置MessageSource的parent MessageSource.
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // 如果未注册任何父MessageSource,则仅将父上下文的MessageSource设置为父MessageSource
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageSource [" + this.messageSource + "]");
        }
    }
    // beanFactory中不包含名字为messageSource的Bean
    else {
        // 新建DelegatingMessageSource对象
        DelegatingMessageSource dms = new DelegatingMessageSource();
        // 设置DelegatingMessageSource的parent MessageSource
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        // 向BeanFactory中注册MessageSource
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                         "': using default [" + this.messageSource + "]");
        }
    }
}

第八步 初始化事件广播

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 检查配置中是否有applicationEventMulticaster的Bean定义
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        // 如果有则获取(实例化Bean)
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        // 如果没有手动创建SimpleApplicationEventMulticaster的实例
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        // 把创建的SimpleApplicationEventMulticaster注册到BeanFactory
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                         APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                         "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

ApplicationContext中的事件处理是通过ApplicationEvent抽象类和ApplicationListener接口实现的。将实现ApplicationListener接口的Bean部署到上下文中,那么每次将ApplicationEvent发布到ApplicationContext时,该Bean都会得到通知。本质上,这是标准的观察者设计模式。

观察者模式

  • Subject:抽象主题类。保存对所有观察者对象的引用,每个主题都可以有任意数量的观察者。该接口可以添加和删除观察者对象

  • ConcreteSubject:具体主题。将状态保存到具体观察者对。在主题内部发生改变时,给所有登记的观察者发出通知。

  • Observer:抽象观察者。为所有具体的观察者定义接口,在得到主题通知时更新自己。

  • ConcreteObserver:具体观察者。实现更新接口,以使自身状态和主题状态同步。

具体实现

抽象被观察者接口

public interface Subject {
    // 添加观察者
    public void addObserver(Observer o);
    // 删除观察者
    public void removeObserver(Observer o);
    // 通知观察者
    public void notifyObserver();
}

抽象观察者接口

public interface Observer {
    // 当被观察者调用notify()方法时,观察者的update()方法会被回调
    public void update(String message);
}

定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。

/**
 * 被观察者
 * 实现了Subject接口,对Subject接口的三个方法进行了具体实现
 */
public class ConcreteSubject implements Subject {
    
    // 保存观察者的集合
    private List<Observer> list;
    private String message;
    
    public ConcreteSubject() {
        list = new ArrayList<Observer>();
    }
    
    @Override
    public void addObserver(Observer o) {
        list.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    //遍历
    @Override
    public void notifyObserver() {
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }
    
    public void setMessage(String s) {
        this.message = s;
        System.out.println("服务消息: " + s);
        //消息更新,通知所有观察者
        notifyObserver();
    }
}

具体观察者

public class User implements Observer {

    private String name;
    private String message;
    
    public User(String name) {
        this.name = name;
    }
    
    @Override
    // 实现update方法
    public void update(String message) {
        this.message = message;
        read();
    }

    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        ConcreteSubject cs = new ConcreteSubject();

        Observer user1 = new User("Zhangsan");
        Observer user2 = new User("Lisi");
        Observer user3 = new User("Wangwu");

        cs.addObserver(user1);
        cs.addObserver(user2);
        cs.addObserver(user3);
        cs.setMessage("发布了消息1");

        System.out.println("----------------------------------------------");
        cs.removeObserver(userZhang);
        cs.setMessage("发布了消息2");
    }
}

事件驱动机制

事件驱动的常见形式便是发布-订阅模式。

在跨进程的通信间,我们通常采用引入 MQ (消息队列) 来实现消息的发布和订阅。目前主流应用的架构中,均采用消息的发布-订阅模式来进行大型分布式系统的解耦。使得数据生产方和使用方分离,同时 MQ 还可起到削峰等作用。

同一进程内很多时候也需要这种事件驱动机制来进行逻辑解耦。

事件机制主要由三个部分组成:

  • 事件对象:事件实体。封装事件源对象和事件,在事件源和监听器之间传递信息

  • 监听器:监听事件对象。事件发生时处理回调

  • 事件源:事件发生的起源。注册监听,对事件进行响应。

Java的事件机制

Java 提供了事件相关的接口定义:

  • 事件对象:EventObject 自定义事件对象需要继承该类

  • 监听器:EventListener 事件监听器接口

  • 事件源:不需要实现任何接口,Java 中也没给出相应的定义

 

示例

事件对象

public class JDKEventObject extends EventObject {

    private Object source;

    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public JDKEventObject(JDKEventSource source) {
        super(source);
        this.source = source;
    }

    @Override
    public Object getSource() {
        return source;
    }
}

监听器

public interface JDKEventListener extends EventListener {
    public void handleEvent(JDKEventObject event);
}

事件源

public class JDKEventSource {
    private Set<EventListener> listeners = new HashSet();

    private String message;

    public void addListener(EventListener event) {
        listeners.add(event);
    }

    public void removeListener(EventListener event) {
        if (listeners.contains(event))
            listeners.remove(event);
    }

    public void fireEvent() {
        Iterator<EventListener> iter = listeners.iterator();
        while (iter.hasNext()) {
            JDKEventListener listener = (JDKEventListener) iter.next();
            listener.handleEvent(new JDKEventObject(this));
        }
    }
}

测试类

public class JDKEventTest {
    public static void main(String[] args) {
        JDKEventSource eventSource = new JDKEventSource();

        eventSource.addListener(new JDKEventListener() {
            @Override
            public void handleEvent(JDKEventObject event) {
                System.out.println("事件1......");
            }
        });
        eventSource.addListener(new JDKEventListener() {
            @Override
            public void handleEvent(JDKEventObject event) {
                System.out.println("事件2......");
            }
        });
        eventSource.fireEvent();
    }
}

事件处理机制在某种程度上与发布-订阅模式非常相似,事件监听器的角色与观察者类似,事件源则充当了被观察对象。事件源状态触发后,主动发起通知给监听器,监听器完成各种后续处理。

Spring事件机制

Spring内置事件:

事件类

说明

ContextRefreshedEvent

ApplicationContext初始化或刷新时触发该事件。通常在Spring加载或刷新应用上下文时,同事也想刷新预加载的资源,就可以通过监听ContextRefreshedEvent来做这样的事情。这里的“初始化”是指所有Bean均已加载,检测到并激活了BeanPostProcessors,已预先实例化单例并且可以使用ApplicationContext对象。只要上下文尚未关闭,选用的ApplicationContext支持这种“热”刷新(如:XmlWebApplicationContext支持热刷新,但GenericApplicationContext不支持),刷新可以被多次触发。

ContextStartedEvent

ApplicationContext启动时触发该事件。"Started" 意味着所有Lifecycle Bean会获得启动事件。 通常,此事件用于在显式停止后重新启动Bean时,也可以用于启动尚未配置为自动启动的组件。

ContextStoppedEvent

ApplicationContext被停止时触发该事件。"Stopped"是指所有Lifecycle Bean都收到一个明确的停止事件。已停止的上下文可以通过start()调用重新启动

ContextClosedEvent

ApplicationContext被关闭时触发该事件。 "Closed" 意味着容器管理的所有单例Bean都被销毁。关闭的上下文表示容器生命周期结束,它不能刷新或重新启动。

RequestHandledEvent

基于Web应用的事件,当一个HTTP请求完成后,触发该事件。该事件仅适用于使用DispatcherServlet的Web应用程序。

容器生命周期

BeanPostProcessor及Bean的初始和销毁回调这些事件都是建立在容器已经成功启动的基础上,如果我们想在容器本身的生命周期。

 

// 生命周期接口,任何Spring管理的对象都可以实现该接口
public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}

// 管理ApplicationContext生命周期
public interface LifecycleProcessor extends Lifecycle {
    void onRefresh();
    void onClose();
}

public interface SmartLifecycle extends Lifecycle, Phased {
    // Lifecycle Bean是否自动启动
    boolean isAutoStartup();

    // 停止的时候执行回调,默认超时时间30秒
    void stop(Runnable callback);
}

// Phased最小的对象首先启动,停止时,顺序和启动时相反
public interface Phased {
    // SmartLifecycle的实现类默认Phase为0
    int getPhase();
}

常规的Lifecycle接口只在容器上下文显式的调用start()/stop()方法时,才会去回调Lifecycle实现类的start/stop方法逻辑。并不意味着在上下文刷新时自动启动。

另外,LifeCycle Bean在销毁之前不能保证会收到停止通知。正常关闭时,所有Lifecycle Bean在销毁回调之前首先会收到停止通知,但是在上下文的生命周期内进行热刷新或中止刷新尝试时,只会调用destroy方法。

// 实现Lifecycle的测试类
public class TestLifeCycle implements Lifecycle {

    private boolean running = false;

    public TestLifeCycle() {
        System.out.println("TestLifeCycle.......");
    }

    @Override
    public void start() {
        System.out.println("TestLifeCycle.start().......");
        running = true;
    }

    @Override
    public void stop() {
        System.out.println("TestLifeCycle.start().......");
        running = false;
    }

    @Override
    public boolean isRunning() {
        return running;
    }
}

// 实现SmartLifecycle的测试类
public class TestSmartLifecycle implements SmartLifecycle {

    private boolean running = false;

    public TestSmartLifecycle() {
        System.out.println("TestSmartLifecycle.......");
    }

    @Override
    public boolean isAutoStartup() {
        return true;
    }

    @Override
    public int getPhase() {
        return 10000;
    }

    @Override
    public void start() {
        System.out.println("TestSmartLifecycle.start().......");
        running = true;
    }

    @Override
    public void stop() {
        System.out.println("TestSmartLifecycle.stop().......");
        running = false;
    }

    @Override
    public void stop(Runnable callback) {
        System.out.println("TestSmartLifecycle.stop(Runnable callback).......");
        running = false;
    }

    @Override
    public boolean isRunning() {
        return running;
    }
}

事件机制

Spring事件机制中除了事件对象和监听者者两个角色之外,“事件广播器”则负责把事件转发给监听者:

类名

描述

ApplicationEvent

Spring提供的事件类,继承自 EventObject 类

ApplicationListener

事件监听者,该类接收一个泛型,供 ApplicationEventPublisher 在发布事件时选择 EventListener

ApplicationEventPublisher

封装事件发布功能的接口,通知所有在 Spring 中注册的该事件的监听者进行处理

ApplicationEventPublisherAware

Spring 提供的 Aware 接口之一,实现该接口的 Bean 可以获取 ApplicationEventPublisher 并进行发布事件

ApplicationEventMulticaster

管理多个ApplicationListener对象并向其发布事件的接口

示例

Spring 中,不需要我们手动进行监听器注册。ApplicationListener 对象一旦在 Spring 容器中被注册,Spring 会进行监听器的注册,实现事件的监听。

服务类

 

// Spring容器检测到Service实现了ApplicationEventPublisherAware接口,会自动调用setApplicationEventPublisher
public class SpringService implements ApplicationEventPublisherAware {

    private List<String> nameList;
    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void setNameList(List<String> list) {
        this.nameList = list;
    }

    // 要发布自定义ApplicationEvent,需要在ApplicationEventPublisher上调用publishEvent方法
    public void sendMessage(String name) {
        if (nameList.contains(name)) {
            publisher.publishEvent(new SpringEvent(this, name));
            return;
        }
    }
}

监听器

// 要接收自定义的ApplicationEvent,需要实现ApplicationListener监听器
public class SpringListener implements ApplicationListener<SpringEvent> {

    String notifier;

    public void setNotifier(String notifier) {
        this.notifier = notifier;
    }

    @Override
    public void onApplicationEvent(SpringEvent event) {
        System.out.println("onApplicationEvent: "+ notifier);
    }
}

事件类

public class SpringEvent extends ApplicationEvent {

    String name;

    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public SpringEvent(Object source, String name) {
        super(source);
        this.name = name;
    }
}

第九步 初始化主题

protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
}

SpringMVC框架主题可以设置应用程序的整体外观,从而增强用户体验。主题是静态资源的集合,通常有css样式表和图片构成,这些css样式和图片会直接影响应用程序的视觉样式。

要在Web应用中使用主题,必须实现ThemeSource接口,WebApplicationContext接口就扩展了ThemeSource,但将其职责委托给专用的实现。

默认委托将是ResourceBundleThemeSource,该实现从类路径的根加载主题属性文件。要使用自定义ThemeSource或需要配置ResourceBundleThemeSource的属性,可以在应用程序上下文中注册使用保留名称'themeSource'的Bean,Web应用程序上下文会自动检测到具有'themeSource'名称的Bean并使用它。

主题使用示例

SpringMVC配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<mvc:default-servlet-handler />
	<mvc:annotation-driven  />

	<context:component-scan base-package="xxx.xxx" />

	<!-- 视图解析 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/" />
		<property name="suffix" value=".jsp" />
	</bean>

	<!-- Theme主题资源 -->
	<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
		<property name="basenamePrefix" value="theme." />
	</bean>

	<!-- Theme主题解析器 -->
	<bean id="themeResolver" class="org.springframework.web.servlet.theme.CookieThemeResolver">
		<property name="defaultThemeName" value="blue" />
	</bean>

	<!-- Theme主题拦截器 -->
	<mvc:interceptors>
		<bean id="themeInterceptor" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
			<property name="paramName" value="theme" />
		</bean>
	</mvc:interceptors>
</beans>

主题资源文件

blue.properties和gray.properties两个属性配置文件存放到resources资源目录下面。

blue.properties

------------------------------
blue.properties
------------------------------
# css对应位置
styleSheet=/css/blue.css
# 图片对应位置
background=images/blue.png

gray.properties

------------------------------
gray.properties
------------------------------
# css对应位置
styleSheet=/css/gray.css
# 图片对应位置
background=images/gray.png

前端页面

JSP代码中引用主题文件的键。在JSP中,通常使用spring:theme标签来执行此操作,该标签与spring:message标签的使用方法非常相似。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type="text/css"/>
<title>Title</title>
</head>
<body style="background: url(<spring:theme code='background'/>)">
<a href="?theme=blue">blue</a> - <a href="?theme=gray">gray</a>
</body>
</html>

源码解析

public static ThemeSource initThemeSource(ApplicationContext context) {
    // 判断容器中是否包含"themeSource"的Bean
    if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
        // 如果包含则实例化这个themSource
        ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
        // 设置themeSource的父themeSource
        if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
            // 用来表示层级关系的ThemeSource对象
            HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
            if (hts.getParentThemeSource() == null) {
                hts.setParentThemeSource((ThemeSource) context.getParent());
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Using ThemeSource [" + themeSource + "]");
        }
        return themeSource;
    }
    else {
        // 如果context中不包含"themeSource"的定义
        HierarchicalThemeSource themeSource = null;
        // 如果context的parent是ThemeSource实例,则设置该contexnt的父ThemeSource
        if (context.getParent() instanceof ThemeSource) {
            // 实例化一个DelegatingThemeSource
            themeSource = new DelegatingThemeSource();
            themeSource.setParentThemeSource((ThemeSource) context.getParent());
        }
        else {
            // 否则,实例化一个ResourceBundleThemeSource
            themeSource = new ResourceBundleThemeSource();
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
                         "': using default [" + themeSource + "]");
        }
        return themeSource;
    }
}

第十步 注册事件监听

protected void registerListeners() {
    // 注册静态指定的监听器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 从BeanFactory中获取listener的名称,并注册
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 发布早期事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

事件广播类图 

说明

ApplicationEventMulticaster

管理多个监听器并向其发布事件对象的接口

AbstractApplicationEventMulticaster

提供监听器注册/管理功能的抽象实现

SimpleApplicationEventMulticaster

将所有事件多播到所有已注册的监听器,让监听器忽略它们不感兴趣的事件。默认情况下,所有监听器在线程中被调用。

源码解读

 

public void addApplicationListener(ApplicationListener<?> listener) {
    synchronized (this.retrievalMutex) {
        Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
        // 如果代理的目标监听器也已经注册到多播器,为了避免两次都调用相同的监听器
        // 从多播器移除目标监听器
        if (singletonTarget instanceof ApplicationListener) {
            this.defaultRetriever.applicationListeners.remove(singletonTarget);
        }
        this.defaultRetriever.applicationListeners.add(listener);
        this.retrieverCache.clear();
    }
}

@Override
public void addApplicationListenerBean(String listenerBeanName) {
    synchronized (this.retrievalMutex) {
        this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
        this.retrieverCache.clear();
    }
}

// 获取喝Event匹配的事件类型,不匹配的排除在外
protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {
    // 获取事件源
    Object source = event.getSource();
    // 获取事件类型
    Class<?> sourceType = (source != null ? source.getClass() : null);
    // 使用事件源和事件类型构造缓存Key
    ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

    // 在缓存中通过Key查找是否存在缓存
    ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
    if (retriever != null) {
        // 如果缓存中存在,则直接返回
        return retriever.getApplicationListeners();
    }

    // 通过类是否在classLoader或者parent classLoader中来判断类是否是可以缓存的
    if (this.beanClassLoader == null ||
        (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
         (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
        // 同步缓存
        synchronized (this.retrievalMutex) {
            // 通过Key获取缓存
            retriever = this.retrieverCache.get(cacheKey);
            if (retriever != null) {
                // 缓存不为空,则返回
                return retriever.getApplicationListeners();
            }
            // 构造ListenRetriever
            retriever = new ListenerRetriever(true);
            Collection<ApplicationListener<?>> listeners =
                retrieveApplicationListeners(eventType, sourceType, retriever);
            this.retrieverCache.put(cacheKey, retriever);
            return listeners;
        }
    }
    else {
        // 无ListenerRetriever缓存,不需要同步
        return retrieveApplicationListeners(eventType, sourceType, null);
    }
}

// 检索指定事件和源类型的监听器
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
    ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {

    // List为要返回的监听器
    List<ApplicationListener<?>> allListeners = new ArrayList<ApplicationListener<?>>();

    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;
    synchronized (this.retrievalMutex) {
        // 使用成员变量defaultRetriever初始化listeners
        listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
        // 使用成员变量defaultRetriever初始化listenerBeans
        listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
    }
    for (ApplicationListener<?> listener : listeners) {
        // 确定监听器是否支持指定的事件
        if (supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                // 有缓存的情况(有传参决定)
                retriever.applicationListeners.add(listener);
            }
            allListeners.add(listener);
        }
    }
    if (!listenerBeans.isEmpty()) {
        BeanFactory beanFactory = getBeanFactory();
        for (String listenerBeanName : listenerBeans) {
            try {
                // BeanFactory中获取Class
                Class<?> listenerType = beanFactory.getType(listenerBeanName);
                
                if (listenerType == null || supportsEvent(listenerType, eventType)) {
                    // 从BeanFactory中获取listener
                    ApplicationListener<?> listener =
                        beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    // allListeners中不包含该监听器,并确定监听器是否支持指定的事件
                    if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                        if (retriever != null) {
                            // 有缓存的情况(有传参决定)
                            retriever.applicationListenerBeans.add(listenerBeanName);
                        }
                        allListeners.add(listener);
                    }
                }
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Singleton listener instance (without backing bean definition) disappeared -
                // probably in the middle of the destruction phase
            }
        }
    }
    // 对Listener进行排序
    AnnotationAwareOrderComparator.sort(allListeners);
    return allListeners;
}

第十一步 完成初始化

 

// 完成Context的BeanFactory初始化,并完成所有剩余的单例Bean的初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 为context上下文初始化conversion service
    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));
    }

    // 如果之前没有嵌入值解析器注册,则注册默认的嵌入值解析器
    // 所谓嵌入值解析器主要用于解析注解属性值
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
            @Override
            public String resolveStringValue(String strVal) {
                return getEnvironment().resolvePlaceholders(strVal);
            }
        });
    }

    // 初始化LoadTimeWeaverAware
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }

    // 停止使用TempClassLoader
    beanFactory.setTempClassLoader(null);

    // 冻结Bean定义配置(Bean定义不会被修改或进一步后处理),因为下一步会实例化对象
    beanFactory.freezeConfiguration();

    // 实例化所有剩余的单例对象(非懒加载的)
    beanFactory.preInstantiateSingletons();
}

源码解读

preInstantiateSingleton

// 确保所有非延迟初始化单例都被实例化
public void preInstantiateSingletons() throws BeansException {
    if (logger.isDebugEnabled()) {
        logger.debug("Pre-instantiating singletons in " + this);
    }

    // 遍历beanDefinitionNames副本以允许使用init方法注册新的BeanDefinition
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    // 触发所有非懒加载单例Bean的初始化
    for (String beanName : beanNames) {
        // 根据Bean的名称获取MergedBeanDefinition
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 判断该beanName是不是一个FactoryBean
            if (isFactoryBean(beanName)) {
                // 获取FactoryBean实例。通过FactoryBean的getBean方法可以获取FactoryBean创建的Bean实例
                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 {
                // 如果beanName对应的不是FactoryBean,则通过beanName获取Bean实例
                getBean(beanName);
            }
        }
    }

    // 触发所有实现SmartInitializingSingleton接口的Bean的初始化后回调
    for (String beanName : beanNames) {
        // 获取对应beanName的实例
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            // 判断是否实现了SmartInitializingSingleton接口
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

最后一步 完成刷新

protected void finishRefresh() {
    // 为上下文初始化生命周期处理器
    initLifecycleProcessor();

    // 将刷新事件传播到生命周期处理器
    getLifecycleProcessor().onRefresh();

    // 发布刷新完毕事件到对应的监听器
    publishEvent(new ContextRefreshedEvent(this));

    // 注册Mbean
    LiveBeansView.registerApplicationContext(this);
}

Spring使用BeanPostProcessor来处理可以找到的任何接口实现并调用具体的方法。如果需要自定义功能或其他生命周期行为,Spring并不提供现成的功能,需要自己实现BeanPostProcessor。

除了初始化和销毁回调外,Bean对象还可以实现Lifecycle接口,以便这些Bean可以在容器自身的生命周期驱动下进行start和stop过程。Lifecycle接口为具有生命周期要求的对象定义了基本方法。

当ApplicationContext接收到开始和停止信号时,它会调用那些关联到在该上下文中的所有Lifecycle实现类(如:启动和停止某些后台进程)。

解码解读

org.springframework.context.support.AbstractApplicationContext

// 初始化生命周期处理器
protected void initLifecycleProcessor() {
    // 获取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 判断BeanFactory中是否已经定义过lifecycleProcessor
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        // 如果定义过lifecycleProcessor,则使用beanFactory中的定义给lifecycleProcessor赋值
        this.lifecycleProcessor =
            beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        if (logger.isDebugEnabled()) {
            // 日志打印
        }
    }
    else {
        // 如果BeanFactory中没有定义lifecycleProcessor,则构造一个DefaultLifecycleProcessor
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        // 设置defaultProcessor的BeanFactory
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        // 将defaultProcessor以单例的形式注册到BeanFactory的生命周期管理器
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate LifecycleProcessor with name '" +
                         LIFECYCLE_PROCESSOR_BEAN_NAME +
                         "': using default [" + this.lifecycleProcessor + "]");
        }
    }
}

org.springframework.context.support.DefaultLifecycleProcessor

private void startBeans(boolean autoStartupOnly) {
    // 获取所有的Lifecycle接口实现类
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    // 按phase进行分组存储
    Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
    for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
        Lifecycle bean = entry.getValue();
        // 如果参数autoStartupOnly不等于true,或者bean是SmartLifecycle实现类并且autoStartup=true
        // autoStartupOnly=true  代表本次刷新为自动启动,触发所有自动启动的SmartLifecycle实现类
        // autoStartupOnly=false 代表本次刷新为显式调用,触发所有的Lifecycle实现类启动
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            // 获取Lifecycle Bean的phase,phase默认为0
            int phase = getPhase(bean);
            // 根据phase获取对应的分组
            LifecycleGroup group = phases.get(phase);
            if (group == null) {
                // 如果没有分组,则新建一个分组
                group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                // 把phase和对应的group放入到集合
                phases.put(phase, group);
            }
            // 把对应的Lifecycle Bean放到对应的分组中
            group.add(entry.getKey(), bean);
        }
    }
    // 遍历分组后的集合
    if (!phases.isEmpty()) {
        List<Integer> keys = new ArrayList<Integer>(phases.keySet());
        // 根据分组phase进行排序
        Collections.sort(keys);
        for (Integer key : keys) {
            // 根据分组顺序依次启动Lifecycle Bean
            phases.get(key).start();
        }
    }
}

// 遍历集合成员,执行Lifecycle实现类的start()函数回调
public void start() {
    if (this.members.isEmpty()) {
        return;
    }
    if (logger.isInfoEnabled()) {
        logger.info("Starting beans in phase " + this.phase);
    }
    // 对分组内的member进行排序
    Collections.sort(this.members);
    for (LifecycleGroupMember member : this.members) {
        if (this.lifecycleBeans.containsKey(member.name)) {
            // 启动Lifecycle Bean
            doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
        }
    }
}

private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
    Lifecycle bean = lifecycleBeans.remove(beanName);
    if (bean != null && bean != this) {
        // 根据beanName获取相应的依赖Bean
        String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName);
        // 遍历依赖Bean
        for (String dependency : dependenciesForBean) {
            // 递归。先回调依赖Bean的start函数(如果依赖Bean是Lifecycle实现类)
            doStart(lifecycleBeans, dependency, autoStartupOnly);
        }

        if (!bean.isRunning() &&
            (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
            if (logger.isDebugEnabled()) {
                // 打印日志
            }
            try {
                // 执行Lifecycle实现类的start()函数回调
                bean.start();
            }
            catch (Throwable ex) {
                throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Successfully started bean '" + beanName + "'");
            }
        }
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring启动流程解析(总) 的相关文章

  • 附录3:Anolis 龙蜥 下载

    以语雀 文档为准 视频演示 点击查看 bilibili 官网 xff1a https openanolis cn 7 7 正式版 https mirrors openanolis cn anolis 7 7 isos GA x86 64 7
  • 附录4:Ubuntu 乌班图 下载

    以语雀 文档为准 https releases ubuntu com https old releases ubuntu com releases 版本号 版本代号 下载地址 14 04 5 Trusty Tahr https old re
  • 小工具1:tcping

    以语雀 文档为准 说明 tcping exe 是一个控制台应用程序 xff0c 其操作类似于 ping xff0c 但它在tcp端口上工作 在 Windows 上要查看指定 IP 端口 是否连通 xff0c 通常要使用 telnet xff
  • 小工具2:Windows curl.exe

    以语雀 文档为准 GitHub 仓库 xff1a https github com curl curlGitHub 仓库 Windows 版 xff1a https github com curl curl for win下载页面 xff1
  • 小工具3:Windows tail.exe

    以语雀 文档为准 文件 xff1a tail zip xff0c 文件来源于网络 xff0c 用于实时查看文件内容 xff0c 与 Linux 的 tail 有相同的用法 下载上述文件 xff0c 解压 xff0c 将 tail exe 放
  • 小工具4:Windows cports.exe

    以语雀 文档为准 文件 cports zip xff0c 文件来源于网络 xff0c 用于实时查看端口占用情况 xff0c 使用管理员权限运行时 xff0c 可杀端口 下载上述文件 xff0c 解压 xff0c 将 cports exe 放
  • 为何在 node 项目中使用固定版本号,而不使用 ~、^?

    以语雀 文档为准 使用 时吃过亏希望版本号掌握在自己手里 xff0c 作者自己升级 xff08 跟随官方进行升级 xff0c 就算麻烦作者 xff0c 也不想麻烦使用者 xff09 虽然 pnpm 很好用 xff0c 但是不希望在项目中用到
  • 导读 2、kubernetes(k8s)导读

    以语雀 文档为准 内容来自 Kubernetes 权威指南 第5版等 kubernetes 是什么 xff1f kubernetes是一个全新的基于容器技术的分布式架构领先方案 xff0c 是容器云的优秀平台选型方案 xff0c 已经成为新
  • 区块链——脱坑truffle

    使用truffle构建一个智能合约 实现输出 helloworld 的功能 网上有很多帖子 但也有很多坑 这里展示我的搭建过程 帮助大家绕过那些麻烦 一 安装web3 solc truffle npm g install solc npm
  • 使用fescar遇到can not register RM,err:can not connect to fescar-server.

    前提 如果你看到了这篇文章 xff0c 说明你已经成功跑起了阿里爸爸fescar官方提供的example和server xff0c 并且你的客户端和服务端之间心跳正常 xff0c 但是当客户端进行事务操作时却提示以下错误 com span
  • Arch常用软件

    常用软件 开发 gitandroid studiovim 图形界面 网络 pacman S networkmanager 启动其提供的服务 systemctl start NetworkManager service 让服务开机自启 sys
  • CentOS可以使用的yum仓库地址

    name 61 CentOS 6 6 Base baseurl 61 http mirrors aliyun com centos vault 6 6 os x86 64 gpgcheck 61 1 gpgkey 61 http mirro
  • pyqt错误:Unresolved reference 和 正确安装pycharm+python+pyqt5

    写如下代码 xff1a span class hljs keyword import span sys span class hljs keyword from span PyQt5 span class hljs keyword impo
  • 以下是adb工具包最新Google官方版下载地址:

    以下是adb工具包最新Google官方版下载地址 xff1a ADB和Fastboot for Windows https dl google com android repository platform tools latest win
  • java.lang.UnsupportedOperationException 及resultMap相关知识

    起因 今天在请求数据库数据时报错java lang UnsupportedOperationException xff0c 从字面上理解错误的含义就是不支持的操作异常 xff0c 后面定位到错误发生在数据库sql语句中 xff0c 具体原因
  • Spring Boot配置类处理

    ConfigurationClassPostProcessor处理所有配置类 xff0c 包括 64 Component 64 Bean 64 Import注解等 由于配置类可能会引入新的配置类 xff0c 新的配置类也需要被处理 xff0
  • 数据库范式1NF 2NF 3NF详细阐述

    范式 xff1a 关系数据库中的关系是要满足一定要求的 xff0c 满足不同程度要求的不同范式 满足最低要求的叫第一范式 xff0c 简称1NF xff0c 在第一范式中满足进一步要求的为第二范式 xff0c 其余以此类推 通俗来说是满足数
  • 记一次 Native Crash Abort message:‘FORTIPY :vsprintf:prevented 33-byte write into 32-byte buffer ’

    先贴上关键日志 第一眼看到日志 xff0c 以为是缺少了Arm64 的so文件 xff0c 查看后发现并没缺少 xff1b 无奈之下 xff0c 只有复现这个Crash xff0c 一点点缩小排查范围 xff1b 最终将问题的矛头指向了项目
  • spring Bean的完整生命周期

    spring bean的完整生命周期 1 1 容器启动时 BeanFactoryPostProcessor gt postProcessBeanFactory Spring IoC容器允许BeanFactoryPostProcessor在容
  • 1秒学会 Vim 插件管理

    Vim pathogen 通常情况下安装vim插件 xff0c 通常是将所有的插件和相关的doc文件都安装在中一文件夹中 xff0c 如将插件全部安装在 usr share vim vim73 plugin 目录下 xff0c 将帮助文档全

随机推荐

  • 【树莓派4B】Manjaro-ARM系统下配置VNC以及遇到的问题

    在两三个小时内经历了各种尝试之后 xff0c 终于成功 xff0c 现在记录一下过程 xff0c 以免下次忘记 系统 xff1a 我实在树莓派4B 8G版上安装了Manjaro 1 下载 wget https github com azal
  • 【硬件调试】串口乱码原因汇总

    一般有以下几种原因 xff0c 列举一下提醒自己 1 波特率出错或者其他串口设置出错 2 三线即可进行通信 xff0c 未接地或者接触不良 xff0c TTL 232 TX RX接反 xff0c 485 A B接反 3 如果接电脑可以通信
  • 真实面试题-高并发如何设置JVM参数

    阿里终面 xff1a 每天100w次登陆请求 xff0c 8G内存该如何设置JVM参数 设置内存大小 由于服务器只有8G内存 xff0c 需要合理分配内存给JVM xff0c 避免过度分配导致内存不足 xff0c 也避免分配不足导致频繁的垃
  • 项目切换分支后突然kotlin not configured

    从其他分支切换回来新功能开发分支后提示kotlin not configured 搜索网上提示是版本问题 要将jre8去掉 如 implementation 39 org jetbrains kotlin kotlin stdlib jre
  • 从安卓系统USB升级包里提取system.img、boot.img和recovery.img在内的镜像文件

    1 前言 如果你拿到一个USB升级包 xff0c 你会发现升级包的结构基本相似 但是里面并不是直接就有包括system img boot img和recovery img在内的镜像文件 如果我们需要在Android手机上获取Magisk 提
  • 使用PE微盘制作启动U盘变成两个盘符后,恢复原始状态

    在利用好系统U盘启动制作了U盘启动盘后 xff0c 我们就可以重装系统了 重装系统后 xff0c 有些朋友想要将U盘启动盘复原成普通U盘 xff0c 但发现仅仅靠格式化还不能完全释放空间 xff0c 这该怎么办呢 xff1f 别着急 xff
  • Idea搭建第一个Vue脚手架项目和遇到的问题

    官方教程传送门 新旧版的命令和项目结构不太一样 xff0c 具体可以看上面的官方文档 配置环境 见https blog csdn net qq 33189961 article details 106970036 在IDEA新建static
  • docker部署nodejs项目

    本文主要分享使用docker部署nodejs项目 使用docker部署项目主要分为三步 1 创建nodejs项目 编写package json为项目安装依赖所用 34 name 34 34 expressPro 34 34 version
  • Android 开发跨进程大图

    对于跨进程传输数据的问题 xff0c 我之前也写了一篇 xff0c 配合阅读效果更好 xff1a Android 开发太难了 xff0c 这异常竟然捕获不到 xff1f 1 抛一个问题 这一天 xff0c 法海想锻炼小青的定力 xff0c
  • linux修改键位:ctrl与caps调换

    ctrl比caps的使用频率更高 xff0c 但是ctrl的位置却对小拇指并不友好 有时使用gnome tweak tool设置键位并没有生效 下面介绍两个简单的方法修改键位 1 使用xmodmap修改键位 我们可以使用包管理器轻松安装xm
  • pandas无法打开.xlsx文件,xlrd.biffh.XLRDError: Excel xlsx file; not supported

    原因是最近xlrd更新后只支持 xls文件 所以pandas read excel xxx xlsx 会报错 可以安装旧版xlrd xff0c 在终端中运行 xff1a pip3 uninstall xlrd pip3 install xl
  • python&多路归并

    问题 xff1a 在项目中 xff0c 需从待分析的数据中选出最大的前几名 xff0c 但由于数据量太大 xff0c 直接排序会内存报错 xff0c 因此尝试用多路归并的思路来解决问题 接口 xff1a 一个目录下有x个已排序好的csv 最
  • 03_spring的基本配置

    bean元素的id和name属性 在Spring配置中 xff0c id和name属性都可以表示bean元素的名称 xff0c 不同的是 xff1a id属性 xff0c 遵守XML语法ID约束 必须以字母开始 xff0c 可以使用字母 数
  • Linux服务器的登录与使用

    Linux服务器的登录与使用 关于登录Linux服务器的方式有很多种 xff0c 本文重点介绍了Linux和Windows下的登录和使用Linux服务器的方式 Linux服务器 服务器可看为是一台功能配置强大的电脑 xff0c 有独立的操作
  • Angular2 - [innerHTML] && pipe(把字符串里的 /n 替换成 <br/>)

    需求 把接口返回的使用说明字符串innerHTML出来 xff1b 本来想直接 innerHTML 就可以了 xff0c 但是事不遂人愿 xff0c 那就写个pipe过滤一下 xff1b 过程 接口返回字符串 xff1a 34 coupon
  • vscode ftp-sync 插件使用

    插件安装和配置 1 下载ftp sync插件 extensions中直接搜索安装即可 2 ctrl 43 shift 43 p 选择执行Ftp sync init 配置文件json含义如下 span class token punctuat
  • Ubuntu16.04终端执行`sudo apt-get update`遇到appstream问题

    Ubuntu 16 04 终端执行sudo apt get update遇到问题 E xff1a Problem executing scripts APT Update Post Invoke Success br 39 if usr b
  • Cloudflare5s盾破解|爬虫自动验证|解决方案

    一 什么是Cloudflare5s盾 Cloudflare是一个网站加速和安全服务提供商 Cloudflare 5s盾是指网站防御模式 xff0c 它可以防止恶意流量和攻击 xff0c 如DDoS SQL注入 XSS等 xff0c 保护网站
  • 若依Vue入门——服务器部署篇

    目录 前端 xff0c ruoyi ui 编译 部署 后端 xff0c ruoyi 使用若依前后端分离的Vue 43 Springboot脚手架 xff0c 进行编译与在Windows Server服务器上的部署 使用IDEA作为IDE 使
  • Spring启动流程解析(总)

    一 xff0c Spring启动流程概述 Spring的IoC容器在实现控制反转和依赖注入的过程中 xff0c 可以划分为两个阶段 xff1a 容器启动阶段 Bean实例化阶段 容器初始化 加载配置 分析配置信息 将Bean信息装配到Bea