@Conditional只有滿足一些列條件之后創建一個bean。自己自定義Condition之外,Spring還提供了很多Condition給我們用.
spring.factories文件里每一個xxxAutoConfiguration文件一般都會有下面的條件注解:
@ConditionalOnBean:當容器里有指定Bean的條件下
@ConditionalOnClass:當類路徑下有指定類的條件下
@ConditionalOnExpression:基於SpEL表達式作為判斷條件
@ConditionalOnJava:基於JV版本作為判斷條件
@ConditionalOnJndi:在JNDI存在的條件下差在指定的位置
@ConditionalOnMissingBean:當容器里沒有指定Bean的情況下
@ConditionalOnMissingClass:當類路徑下沒有指定類的條件下
@ConditionalOnNotWebApplication:當前項目不是Web項目的條件下
@ConditionalOnProperty:指定的屬性是否有指定的值
@ConditionalOnResource:類路徑是否有指定的值
@ConditionalOnSingleCandidate:當指定Bean在容器中只有一個,或者雖然有多個但是指定首選Bean
@ConditionalOnWebApplication:當前項目是Web項目的條件下。
上面@ConditionalOnXXX都是組合@Conditional元注解,使用了不同的條件Condition
@ConditionalOnWebApplication注解:
package org.springframework.boot.autoconfigure.condition;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {
}
從源碼我們可以看出,此注解使用的條件是OnWebApplicationCondition類.
從isWebApplication方法可以看出,判斷條件是:
GenericWebApplicationContext是否在類路徑中;
容器中是否有名為session的scope;
當前容器的Enviroment是否為StandardServletEnvironment;
當前的ResourceLoader是否是WebApplicationContext(ResourceLoader是ApplicationContext的頂級接口之一);
我們需要構建ConditionOutcome類的對象來幫助我們,最終通過ConditionOutcome.isMatch方法返回值來確定條件。