개발/spring boot
spring 인터페이스의 구현체를 동적으로 선택
nix-be
2022. 12. 12. 10:22
728x90
1. 내가 원하는 것 : properties에 설정 값에 따라 다른 implement 가 실행되는 것을 구현하고 싶었습니다.
1-1. 비효율적인 implement 생성
단점은 implement 가 추가되면 bean 등록을 해줘야 됩니다.
@PropertySource("classpath:url.properties")
@RestController
@RequiredArgsConstructor
public class BeanImpl2Controller {
private final FserviceImpl fserviceImpl;
private final SserviceImpl sserviceImpl;
@Value("${server.impl}")
private String values;
@GetMapping("/beanImple2")
public String beanimpl() {
switch(values) {
case "FserviceImpl":
fserviceImpl.fire();
break ;
case "SserviceImpl":
sserviceImpl.fire();
break;
}
return values;
}
}
package com.example.demo.domain.diTest.beanImpl2Properties;
public interface BeanService {
public void fire();
}
package com.example.demo.domain.diTest.beanImpl2Properties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class FserviceImpl implements BeanService{
@Override
public void fire() {
System.out.print("test2");
}
}
package com.example.demo.domain.diTest.beanImpl2Properties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class SserviceImpl implements BeanService{
@Override
public void fire() {
System.out.print("test1 ");
}
}
- url.properties
#server.impl = FserviceImpl
server.impl = SserviceImpl
하지만 내가 원하는 그림은 아니였습니다. 그래서 검색을 하여 아래와 같은 제가 원하는 것을 찾게 되었습니다.
1-2. implement를 각자 생성 안 해도 되는 코드
package com.example.demo.domain.diTest.multipleImplement;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@PropertySource("classpath:url.properties")
@RestController
public class MultipleImplController {
private final Map<String,MultipleImplService> multipleImplServiceMap;
@Value("${server2.multipleImpl}")
private String interfaceName;
@Autowired
public MultipleImplController(List<MultipleImplService> multipleImplServices) {
this.multipleImplServiceMap = multipleImplServices.stream()
.collect(Collectors.toMap(MultipleImplService::getISOCountryCode, Function.identity()));
}
@GetMapping("/MultipleImpl")
public String MultipleImple() {
switch(interfaceName) {
case "FirstMultipleImplService":
MultipleImplService impl = multipleImplServiceMap.get("first");
impl.sampleMethod();
break;
case "SecondMultipleImplService":
MultipleImplService impl2 = multipleImplServiceMap.get("second");
impl2.sampleMethod();
break;
}
return "test";
}
}
package com.example.demo.domain.diTest.multipleImplement;
public interface MultipleImplService {
public void sampleMethod();
public String getISOCountryCode();
}
package com.example.demo.domain.diTest.multipleImplement;
import org.springframework.stereotype.Service;
@Service
public class FirstMultipleImplService implements MultipleImplService{
@Override
public void sampleMethod() {
System.out.print("first 1 method");
}
@Override
public String getISOCountryCode() {
return "first";
}
}
package com.example.demo.domain.diTest.multipleImplement;
import org.springframework.stereotype.Service;
@Service
public class SecondMultipleImplService implements MultipleImplService {
@Override
public void sampleMethod() {
System.out.print("second 2 method");
}
@Override
public String getISOCountryCode() {
return "second";
}
}
-url.properties
server2.multipleImpl = FirstMultipleImplService
#server2.multipleImpl = SecondMultipleImplService
3. 위에 코드는 이해하기 어렵기 때문에 쉬운 코드로 예시를 들어보겠습니다.
- 컨트롤러
import com.onetoone.onetoonetest.multiImpl.service.Circle;
import com.onetoone.onetoonetest.multiImpl.service.DrawingService;
import com.onetoone.onetoonetest.multiImpl.service.Rectan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@PropertySource("classpath:url.properties")
@RestController
@RequestMapping("/controller")
public class DrawingController {
private final DrawingService circle;
private final DrawingService rectan;
@Value("${localtion}")
private String type;
public DrawingController(Circle circle, Rectan rectan){
this.circle = circle;
this.rectan = rectan;
}
private DrawingService getType(String type){
return type.equals("center") ? this.circle : this.rectan;
}
@GetMapping("/shapes")
public void drawShapes() {
getType(type).draw();
}
}
- url.properties
localtion=center
- 인터페이스
public interface DrawingService {
public void draw();
}
- implements
@Service
public class Circle implements DrawingService{
@Override
public void draw() {
System.out.println("Circle test 1");
}
}
@Service
public class Rectan implements DrawingService{
@Override
public void draw() {
System.out.println("Rectan test 1");
}
}
728x90