问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Spring Boot中控制使用特定实现类的5种方法

创作时间:
作者:
@小白创作中心

Spring Boot中控制使用特定实现类的5种方法

引用
CSDN
1.
https://blog.csdn.net/kaka_buka/article/details/142455847

在Spring Boot开发中,经常会遇到一个接口有多个实现类的情况。本文将详细介绍5种控制和选择特定实现类的方法,包括使用@Primary注解、@Qualifier注解、自定义注解、基于配置文件的控制以及基于Profiles的实现。

在Spring Boot中如何控制使用特定的实现类

在Spring Boot开发中,通常我们会面临接口有多个实现类的情况。例如,假设我们有一个
NameQueryService
接口,该接口有多个实现类,比如
ANameQueryServiceImpl

BNameQueryServiceImpl
。在某些情况下,我们只希望使用其中一个实现类,而不使用其他实现类。本文将详细介绍如何在Spring Boot中通过多种方式控制和选择想要的实现类。

1. @Primary注解

当有多个实现类时,最简单的方式是使用
@Primary
注解。Spring在自动装配时会优先选择带有
@Primary
注解的实现类。

示例代码:

public interface NameQueryService {
    String queryName();
}
@Service
@Primary
public class ANameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "A Implementation";
    }
}
@Service
public class BNameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "B Implementation";
    }
}

在上述代码中,
ANameQueryServiceImpl
被标记为
@Primary
,因此当Spring自动装配
NameQueryService
接口时,优先使用
ANameQueryServiceImpl

使用示例:

@RestController
public class NameController {
    private final NameQueryService nameQueryService;
    public NameController(NameQueryService nameQueryService) {
        this.nameQueryService = nameQueryService;
    }
    @GetMapping("/name")
    public String getName() {
        return nameQueryService.queryName();
    }
}

当调用
/name
接口时,返回的是
A Implementation
,因为
ANameQueryServiceImpl

@Primary
标记为默认实现。

2. @Qualifier注解

如果需要更加精细地控制具体使用哪个实现类,可以使用
@Qualifier
注解,明确指定使用的实现类名称。

示例代码:

@Service
public class ANameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "A Implementation";
    }
}
@Service
public class BNameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "B Implementation";
    }
}

在需要使用特定实现类的地方,使用
@Qualifier
注解指定:

@RestController
public class NameController {
    private final NameQueryService nameQueryService;
    public NameController(@Qualifier("aNameQueryServiceImpl") NameQueryService nameQueryService) {
        this.nameQueryService = nameQueryService;
    }
    @GetMapping("/name")
    public String getName() {
        return nameQueryService.queryName();
    }
}

在这里,通过
@Qualifier("aNameQueryServiceImpl")
指定了使用
ANameQueryServiceImpl
实现类,而不是
BNameQueryServiceImpl

3. 自定义注解

除了使用Spring的内置注解
@Primary

@Qualifier
外,还可以通过自定义注解来标记实现类,从而灵活控制依赖注入。

示例代码:

首先,创建一个自定义注解:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AService {
}

然后在需要使用的实现类上加上自定义注解:

@Service
@AService
public class ANameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "A Implementation";
    }
}
@Service
public class BNameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "B Implementation";
    }
}

在注入时使用自定义注解:

@RestController
public class NameController {
    private final NameQueryService nameQueryService;
    public NameController(@AService NameQueryService nameQueryService) {
        this.nameQueryService = nameQueryService;
    }
    @GetMapping("/name")
    public String getName() {
        return nameQueryService.queryName();
    }
}

通过这种方式,
@AService
明确标记了使用
ANameQueryServiceImpl
,而无需依赖
@Primary

@Qualifier

4. 基于配置文件的控制

如果希望更加动态地控制使用哪个实现类,可以通过Spring的配置文件进行配置,结合
@ConditionalOnProperty
注解实现不同实现类的选择。

示例代码:

@Service
@ConditionalOnProperty(name = "service.name.type", havingValue = "A")
public class ANameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "A Implementation";
    }
}
@Service
@ConditionalOnProperty(name = "service.name.type", havingValue = "B")
public class BNameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "B Implementation";
    }
}


application.properties
中配置:

service.name.type=A

通过修改配置文件中的
service.name.type
,可以动态选择
ANameQueryServiceImpl

BNameQueryServiceImpl
作为
NameQueryService
的实现。

5. 基于Profiles的实现

Spring的
@Profile
注解可以根据不同的环境使用不同的实现类。例如,在开发环境中使用
ANameQueryServiceImpl
,在生产环境中使用
BNameQueryServiceImpl

示例代码:

@Service
@Profile("dev")
public class ANameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "A Implementation";
    }
}
@Service
@Profile("prod")
public class BNameQueryServiceImpl implements NameQueryService {
    @Override
    public String queryName() {
        return "B Implementation";
    }
}


application.properties
中设置当前激活的Profile:

spring.profiles.active=dev

这样,当激活
dev
环境时,Spring会使用
ANameQueryServiceImpl
,而在
prod
环境时,Spring则会选择
BNameQueryServiceImpl

结论

当一个接口有多个实现类时,Spring Boot提供了多种方式来控制具体使用哪个实现类。可以根据具体的需求,选择使用
@Primary

@Qualifier
、自定义注解、基于配置文件的控制或
@Profile
来灵活地指定实现类。这些方法都可以帮助我们在不同场景下精确地管理和使用实现类。

参考链接

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号