SpringAction学习二、高级装配:补充一

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MASORL/article/details/82657943

关于Spring4 的@profile注解

源码如下:

可以发现,@Profile注解其实是实现了Conditional注解,且传入的实例为ProfileCondition。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
    String[] value();
}

继续前进,进入ProfileCondition.class,源码如下

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.context.annotation;

import java.util.Iterator;
import java.util.List;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.MultiValueMap;

class ProfileCondition implements Condition {
    ProfileCondition() {
    }

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        if (context.getEnvironment() != null) {
            MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
            if (attrs != null) {
                Iterator var4 = ((List)attrs.get("value")).iterator();

                Object value;
                do {
                    if (!var4.hasNext()) {
                        return false;
                    }

                    value = var4.next();
                } while(!context.getEnvironment().acceptsProfiles((String[])((String[])value)));

                return true;
            }
        }

        return true;
    }
}

很明显,该类实现了Condition接口。

首先:通过getAllAnnotationAttributes(Profile.class.getName());获取到了用于@Profile注解的所有属性,那么到底属性指的是什么,通过断点查看下

结果发现,返回的Map中,值是proflie的名称的一个集合(@Profile【({"dev", "asd","ggg"})】

有了值以后,那么就要开始检查以该值为名称的profile到底有没有激活。

首先 进入一遍循环,把profile的第一个值放入value【可以看出,value是一个String[3] 的 数组】

接着,通过Environment的acceptsProfiles方法。该方法用于验证profile是否激活,激活则返回true。acceptsProfiles源码如下 

public boolean acceptsProfiles(String... profiles) {
//先通过断言判断是否为空
        Assert.notEmpty(profiles, "Must specify at least one profile");
        String[] var2 = profiles;
        int var3 = profiles.length;
//开始循环整个数组,对每一个profiles内的值进行判断
        for(int var4 = 0; var4 < var3; ++var4) {
            String profile = var2[var4];
//StringUtils.hasLength(profile)判断profile是否为空
            if (StringUtils.hasLength(profile) && profile.charAt(0) == '!') {
                if (!this.isProfileActive(profile.substring(1))) {
                    return true;
                }
            } else if (this.isProfileActive(profile)) {
                return true;
            }
        }

        return false;
    }

通过acceptsProfiles可以看出,只要有一个profile满足激活,那么就可以返回true。

但是注意:整条语句前加了!

也就是说,当前的profile 为激活时,while中的表达式整体就是false,不再进入循环,执行下一条语句,也就是true。matches返回true的话,bean也就可以被创建。

如果,当前的profile未激活,while中的表达式整体就是true,再次进入循环,判断下一组profile名称是否被激活,一直循环,当所有的profile 名称都被循环了一遍还没有跳出循环,那么说明所有的profile都没被激活,通过

if (!var4.hasNext()) {return false;}

返回flase,无法为该@Profile注释的bean创建。

这就是整个@Profile借助@Conditional来实现创建bean的原理

猜你喜欢

转载自blog.csdn.net/MASORL/article/details/82657943
今日推荐