最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

spring - Add class instance to a map when class use Service annotation - Stack Overflow

programmeradmin4浏览0评论

I use spring boot. Instead of using many if condition based on state of a object to do a process, I search to use a strategy pattern

if (StatutDepositEnum.SAVED.getCode().equals(deposit.status)){
}
else if(){
}



public interface NoticeTemplateService(){
    void apply();
}

@Service
public class ConfirmationNoticeTemplateService implements NoticeTemplateService{
    public void apply(){
    }
}

I know I could put the status name to every class who implement NoticeTemplateService, but because the status has nothing to do with class name, i would like to avoid that

So I search to use deposit status like the key of the map.

@RequiredArgsConstructor
@Service
public class NoticeService{

    public final Map<String, NoticeTemplateService> mapNoticeTemplateService;

    @PostConstruct
    public void init(){
        mapNoticeTemplateService = new HashMap<>();
    }

    public void createNotice(){

     NoticeTemplateService noticeTemplateService = mapNoticeTemplateService.get(deposit.status);

    }

}

How to add instance to the map? All class use Service annotation;

I use spring boot. Instead of using many if condition based on state of a object to do a process, I search to use a strategy pattern

if (StatutDepositEnum.SAVED.getCode().equals(deposit.status)){
}
else if(){
}



public interface NoticeTemplateService(){
    void apply();
}

@Service
public class ConfirmationNoticeTemplateService implements NoticeTemplateService{
    public void apply(){
    }
}

I know I could put the status name to every class who implement NoticeTemplateService, but because the status has nothing to do with class name, i would like to avoid that

So I search to use deposit status like the key of the map.

@RequiredArgsConstructor
@Service
public class NoticeService{

    public final Map<String, NoticeTemplateService> mapNoticeTemplateService;

    @PostConstruct
    public void init(){
        mapNoticeTemplateService = new HashMap<>();
    }

    public void createNotice(){

     NoticeTemplateService noticeTemplateService = mapNoticeTemplateService.get(deposit.status);

    }

}

How to add instance to the map? All class use Service annotation;

Share Improve this question asked 5 hours ago robert trudelrobert trudel 5,76918 gold badges87 silver badges142 bronze badges 3
  • what you want to use as a key of the map? – Geba Commented 5 hours ago
  • like i wrote... "So I search to use deposit status like the key of the map." – robert trudel Commented 5 hours ago
  • sorry, my bad. Missed it – Geba Commented 5 hours ago
Add a comment  | 

2 Answers 2

Reset to default 0

Want you want is a map that holds a reference between Status and the the concrete NoticeServiceImpl that performs the right operation.

@Configuration
public class BeanHolder {
    
    @Bean
    public Map<StatutDepositEnum, NoticeTemplateService> servicesMap(ConfirmationNoticeTemplateService serviceA, RejectionNoticeTemplateService serviceB, ...) {
        return Map.of(
            StatutDepositEnum.SAVED, serviceA,
            StatutDepositEnum.REJECTED, serviceB,
            ....
        );
    }
}

You can inject this Bean wherever you need it.

@RequiredArgsConstructor
@Service
public class NoticeService{

    private final Map<StatutDepositEnum, NoticeTemplateService> mapNoticeTemplateService;

    public void createNotice(){

     NoticeTemplateService noticeTemplateService = mapNoticeTemplateService.get(deposit.status);

     ...

     noticeTemplateService.apply();


    }

}

If you want to use as a key your custom type (e.g. StatusDepositEnum),
then I suggest following

enum StatusDepositEnum {
    REJECTED,
    COMPLETED;
}

interface NoticeTemplateService{
    void apply();
    StatusDepositEnum getStatus();
}

@Service
class ConfirmationNoticeTemplateService implements NoticeTemplateService {
    @Override
    public void apply() {}
    @Override
    public StatusDepositEnum getStatus() {
        return StatusDepositEnum.COMPLETED;
    }
}

@Service
class RejectNoticeTemplateService implements NoticeTemplateService {
    @Override
    public void apply() {}
    @Override
    public StatusDepositEnum getStatus() {
        return StatusDepositEnum.REJECTED;
    }
}

@Service
class NoticeService{

    @Autowired
    private List<NoticeTemplateService> templates;
    private Map<StatusDepositEnum, NoticeTemplateService> statusToTemplate;

    @PostConstruct
    public void init(){
        statusToTemplate = templates.stream()
            .collect(Collectors.toMap(
                    NoticeTemplateService::getStatus,
                    service -> service
            ));
    }

    public void createNotice(){}
}

If you are ok to set bean names, I would suggest to take a look to the approach described in this answer https://stackoverflow/a/63661216/7613649.
For you it will look like this:

@Service("CONFIRM")
class ConfirmationNoticeTemplateService implements NoticeTemplateService {
    @Override
    public void apply() {}
}

@Service("REJECT")
class RejectNoticeTemplateService implements NoticeTemplateService {
    @Override
    public void apply() {}
}

@Service
class NoticeService{
    @Autowired
    private Map<String, NoticeTemplateService> statusToTemplate;
    public void createNotice(){}
}
发布评论

评论列表(0)

  1. 暂无评论