@Conditional的使用

@Conditional 是spirng 4.0引入的註解,可以放在類和方法上 ,標示符合條件的類,spring容器纔會對其實例化
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

	/**
	 * All {@link Condition}s that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();

}

 實現代碼:在spring實例化時會調用 org.springframework.context.annotation.ConditionEvaluator類的shouldSkip方法,代碼:

/**
	 * Determine if an item should be skipped based on {@code @Conditional} annotations.
	 * @param metadata the meta data
	 * @param phase the phase of the call
	 * @return if the item should be skipped
	 */
	public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
		if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
			return false;
		}

		if (phase == null) {
			if (metadata instanceof AnnotationMetadata &&
					ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
				return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
			}
			return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
		}

		List<Condition> conditions = new ArrayList<>();
		for (String[] conditionClasses : getConditionClasses(metadata)) {
			for (String conditionClass : conditionClasses) {
				Condition condition = getCondition(conditionClass, this.context.getClassLoader());
				conditions.add(condition);
			}
		}

		AnnotationAwareOrderComparator.sort(conditions);

		for (Condition condition : conditions) {
			ConfigurationPhase requiredPhase = null;
			if (condition instanceof ConfigurationCondition) {
				requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
			}
            //這個地方 去調用重寫的matches方法,如果重寫matches方法返回false時,直接跳過配置的註解語義
			if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
				return true;
			}
		}

		return false;
	}

 

==============================================分隔線==========================================

直接上代碼

 

Person下有兩個子類  Man和Woman

public interface Person {
    public String birth();
}
public class Man implements Person {
    @Override
    public String birth() {
        return ("This is man");
    }
}
public class Woman implements Person {
    @Override
    public String birth() {
        return("This is woman");
    }
}

分別爲Man和Woman添加條件類

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class ManCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return false;//返回false
    }
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WomanCondition implements Condition {

    /**
     * 返回true 纔會被Spring實例化
     * @param context
     * @param metadata
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return true;
    }
}

添加配置類

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionConfig {
    @Bean("man")
    @Conditional(ManCondition.class)
    public Man getMan(){
        return new Man();
    }

    /**
     * 只有 WomanCondition 中 matches方法返回true 纔會啓用配置
     * @return
     */
    @Bean("woMan")
    @Conditional(WomanCondition.class)
    public Woman getWoMan(){
        return new Woman();
    }
}

main方法

public class ConditionDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);
        context.getBeansOfType(Person.class).forEach((beanName,bean)->{
            System.err.println("Bean Name:"+beanName+" ->"+bean);
        });

    }
}

//響應日記

.......略
17:26:36.085 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
17:26:36.127 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
17:26:36.129 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'woMan'
Bean Name:woMan ->condition.Woman@3427b02d

可以看到,Spring容器Person接口只會實例化一個子類 condition.Woman@3427b02d  

參考文章https://blog.csdn.net/u010502101/article/details/76554564

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章