前言
將Bean交給spring托管很簡單,根據功能在類上添加@Component
,@Service
,@Controller
等等都行,如果是第三方類,也可以通過標有@Configuration
的配置類來進行注入。但並不是所有被注入的bean都用得着,無腦注入會浪費資源。springboot提供了條件化配置,只有在滿足注入條件才實例化。比如自定義一個ServiceHelloService
,希望在spring.profiles.active=local
時才加載。
基礎
springboot中提供了Condition
接口,實現它即可定義自己的條件:
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Arrays;
public class HelloCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return Arrays.stream(context.getEnvironment().getActiveProfiles())
.anyMatch("local"::equals);
}
}
HelloService:
import com.yan.springboot.condition.HelloCondition;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Component
@Conditional(HelloCondition.class)
public class HelloService {
public void sayHi() {
LoggerFactory.getLogger(HelloService.class).info("Hello World!");
}
}
測試:
import com.yan.springboot.service.HelloService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {
@Autowired(required = false)
private HelloService helloService;
@Test
public void test() {
Assert.assertTrue(null == helloService);
}
}
測試通過。
此時在配置文件中加入spring.profiles.active=local
則會報錯(斷言錯誤,helloService存在),可見它已生效。
擴展
Springboot中提供了很多條件化配置的注解,只要輸入@ConditionalOn
就能出現一大堆:
不過比較常用的也就幾種:
/*******************
* Class包含Bean *
******************/
// 容器中有ThreadPoolTaskExecutor類型的bean時才注入
@ConditionalOnBean(ThreadPoolTaskExecutor.class)
@ConditionalOnMissingBean(ThreadPoolTaskExecutor.class)
// 類路徑中有ThreadPoolTaskExecutor類型的bean時才注入
@ConditionalOnClass(ThreadPoolTaskExecutor.class)
@ConditionalOnMissingClass
// 在配置文件中查找hello.name的值,如果能找到並且值等於yan,就注入,如果根本就沒配,也注入,這就是matchIfMissing = true的含義
@ConditionalOnProperty(prefix = "hello", name = "name", havingValue = "yan", matchIfMissing = true)
//只在web環境下注入
@ConditionalOnWebApplication
// java8或以上環境才注入
@ConditionalOnJava(ConditionalOnJava.JavaVersion.EIGHT)