spring?@Conditional的使用與擴展源碼分析
@Conditional的使用
@Conditional可以根據(jù)條件來判斷是否注入某些Bean。
package com.morris.spring.config; import com.morris.spring.condition.LinuxCondition; import com.morris.spring.condition.WindowsCondition; import com.morris.spring.entity.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class ConditionalConfig { // 如果是windows系統(tǒng)就注入bill @Conditional(WindowsCondition.class) @Bean(name = "user") public User bill() { return new User("bill", 22); } // 如果是linux系統(tǒng)就注入linus @Conditional(LinuxCondition.class) public User linus() { return new User("linus", 20); }
WindowsCondition和LinuxCondition都需要實現(xiàn)Condition接口。
WindowsCondition
package com.morris.spring.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class WindowsCondition implements Condition { /** * 根據(jù)條件判斷是否注入對應的Bean * @param conditionContext 應用上下文 * @param annotatedTypeMetadata 加了@Conditional注解的方法的元數(shù)據(jù)信息 * @return */ @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { String osName = conditionContext.getEnvironment().getProperty("os.name"); if(osName.contains("Windows")) { return true; } return false; } }
LinuxCondition
package com.morris.spring.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { String osName = conditionContext.getEnvironment().getProperty("os.name"); if(osName.contains("linux")) { return true; } return false; } }
如果要測試LinuxCondition并不需要再linux系統(tǒng)下運行,只需要的啟動時設置環(huán)境參數(shù):-Dos.name=linux
。
Conditional的擴展
ConditionalOnBean
ConditionalOnBeanc.java
package com.morris.spring.condition; import org.springframework.context.annotation.Conditional; import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnBean { Class<?>[] value() default {}; }
OnBeanCondition.java
package com.morris.spring.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import java.util.Map; public class OnBeanCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnBean.class.getName()); Class<?>[] clazz = (Class<?>[]) annotationAttributes.get("value"); for (Class<?> aClass : clazz) { Map<String, ?> beans = context.getBeanFactory().getBeansOfType(aClass); if(beans.isEmpty()) { return false; } } return true; } }
ConditionalOnProperty
ConditionalOnProperty.java
package com.morris.spring.condition; import org.springframework.context.annotation.Conditional; import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnPropertyCondition.class) public @interface ConditionalOnProperty { String[] value() default {}; }
OnPropertyCondition.java
package com.morris.spring.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import java.util.Map; public class OnPropertyCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName()); String[] propertyArray = (String[]) annotationAttributes.get("value"); for (String property : propertyArray) { if(!context.getEnvironment().containsProperty(property)) { return false; } } return true; } }
源碼分析
如果Condition返回的是false,那么spirng就不會對方法或類進行解析。
org.springframework.context.annotation.ConditionEvaluator#shouldSkip
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) { // 判斷類或方法上面是否有@Conditional注解 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(); // 調(diào)用condition.matches方法 if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) { return true; return false; }
到此這篇關(guān)于spring @Conditional的使用與擴展的文章就介紹到這了,更多相關(guān)spring @Conditional使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
新建springboot項目時,entityManagerFactory報錯的解決
這篇文章主要介紹了新建springboot項目時,entityManagerFactory報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01MyBatisCodeHelperPro最新激活方法(有效方法)
這篇文章主要介紹了MyBatisCodeHelperPro最新激活方法親測有效,非常好用,小編今天以idea2021.2.1為例給大家詳細講解,需要的朋友可以參考下2022-08-08Mybatis collection查詢集合屬性報錯的解決方案
這篇文章主要介紹了Mybatis collection查詢集合屬性報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09