Springboot学习笔记(五)-条件化注入

前言

将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就能出现一大堆:
Springboot学习笔记(五)-条件化注入

不过比较常用的也就几种:

/*******************
 *   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)

相关推荐