MrRobot5 生也有涯,知也无涯

Spring Profile 工作原理及应用

2022-09-07

监控、动态配置等辅助功能,在开发和测试场景中,并不需要。但是会在spring 启动加载过程中拖慢启动速度,开发、自测效率也受影响。

方案:配置spring profile,排除这些配置文件。在开发环境中,只加载关注的配置。

profile 使用示例

<?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" 
    profile="!speed">
    <!-- 开发环境不需要的配置 -->
    <!-- 例如:缓存,连接redis io操作 -->
    <!-- 例如:mq 消费,连接broker io操作 -->
</beans>
@Configuration
public class AppConfig {

    @Bean("dataSource")
    @Profile("development") 
    public DataSource standaloneDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }

    @Bean("dataSource")
    @Profile("production") 
    public DataSource jndiDataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

JVM 配置 -Dspring.profiles.active="speed,profile2"

Code Insight

Bean definition profiles provide a mechanism in the core container that allows for registration of different beans in different environments.

Bean Definition Profiles 文档

①XML Bean Definition Profiles

关键类:org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader

/**
 * 解析并注册beans 标签下声明的bean。 Since:3.1
 */
protected void doRegisterBeanDefinitions(Element root) {

    if (this.delegate.isDefaultNamespace(root)) {
        // "profile"
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            // profile 格式解析,支持分隔符",; "
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            // 判断profile 是否激活,如果不符合快速失败,直接return
            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;
            }
        }
    }

    // 正常解析和注册 bean
    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
}

②@Profile

注解可以在类和方法上使用。

// Spring condition match 特性实现选择性加载, Since:4.0
@Conditional(ProfileCondition.class)
public @interface Profile {

    /**
     * The set of profiles for which the annotated component should be registered.
     */
    String[] value();

}

总结

  • profile 思想应用广泛,常见的还有maven profile。

  • spring profile 提供一整套环境切换的方案,更加简化了工程治理。


Content