Spring @Profile注解使用和源码解析

科技资讯 投稿 5600 0 评论

Spring @Profile注解使用和源码解析

介绍

# Spring注解@Profile实现开发环境,测试环境,生产环境的切换

使用

spring.profiles.active,也可以通过配置jvm参数。

通过Environment设置profile

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(;
context.getEnvironment(.setActiveProfiles("dev";

通过JVM参数设置

可以通过JVM参数来设置环境变量的值,在开发中,这种方式也是使用得比较普遍。

SpringBoot通过yml进行配置

Environment中,这样,spring在后续得流程里面,就能从Environment中获取环境变量,然后进行相应的逻辑处理。

源码解析

BeanDefinition注册

shouldSkip判断,它会筛选出符合的bean,不符合条件的bean则被加入skippedBeanMethods集合中,不会被注册。

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod {
	ConfigurationClass configClass = beanMethod.getConfigurationClass(;
	MethodMetadata metadata = beanMethod.getMetadata(;
	String methodName = metadata.getMethodName(;
		// Do we need to mark the bean as skipped by its condition?
	if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN {
            configClass.skippedBeanMethods.add(methodName;
            return;
	}
            if (configClass.skippedBeanMethods.contains(methodName {
            return;
	}
}

shouldSkip源码

在shouldSkip中,会使用Condition接口,@Profile使用的是ProfileCondition,然后调用matches方法。

    public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationCondition.ConfigurationPhase phase {
        for (Condition condition : conditions {
            ConfigurationCondition.ConfigurationPhase requiredPhase = null;
            if (condition instanceof ConfigurationCondition configurationCondition {
                requiredPhase = configurationCondition.getConfigurationPhase(;
            }
            if ((requiredPhase == null || requiredPhase == phase && !condition.matches(this.context, metadata {
                return true;
            }
        }
        return false;
    }

ProfileCondition匹配

在ProfileCondition的matches方法中,主要就是去Environment中寻找环境变量,然后解析@Profile注解设置的value值,如果Environment中激活的配置中包含当前的配置,包含则能为true,不包含则为false,如上通过setActiveProfiles设置Environment中激活的配置为dev,当前传过来的配置为dev,那么就能匹配上,就能装配进IOC容器。

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata {
        MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName(;
        if (attrs != null {
            for (Object value : attrs.get("value" {
                if (context.getEnvironment(.acceptsProfiles(Profiles.of((String[] value {
                    return true;
                }
            }
            return false;
        }
        return true;
    }

从源码可以看出,其最核心的思想就是是否注册bean的元信息BeanDefinition,因为只有注册了BeanDefinition,后续才能为创建bean提供元数据支持,判断是否注册bean元信息,主要就是从Environment中取出profiles的值,然后和@Profile注解设置的值进行匹配,匹配得上就注册,bean不上就不注册。

总结

今天的分享就到这里,感谢你的观看,下期见!

编程笔记 » Spring @Profile注解使用和源码解析

赞同 (30) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽