在 Spring 中使用策略模式(一)
本文最后更新于365 天前,其中的信息可能已经过时,如有错误请发送邮件到[email protected]

问题出现

问题描述:在Spring Boot环境下使用策略模式,调用 Spring 的 Bean 出现了空指针异常。

// 这是一个很经典的策略模式实现,但是如果这么些就一定会出现上面所述BUG
@Service
public class BussinessServiceImpl implements BussinessService {
    private final Map<Integer, Strategy> strategyMap;

    @Autowired
    public BussinessServiceImpl() {
        this.searchMap = new HashMap<>();
        // 添加具体的策略实现类
        searchMap.put(1, new ConcreteStrategy1());
        searchMap.put(2, new ConcreteStrategy2());
    }

    @Override
    public void search(Integer type, DTO dto) {
        Strategy strategy = strategyMap.get(type);
        if (ObjUtil.isNull(strategy)) {
            return;
        }
        strategy.options(dto);
    }

}
/**
 * 在抽象策略,尽量使用抽象类,不要使用接口,原因在于,有些方法可以提取到父类中使用
 */
@Component
public abstract class Strategy  {
    @Resource
    private BussinessMapper bussinessMapper; // 这里的bussinessMapper一定为空
    // 抽象的业务方法
    public abstract void options(DTO dto);

    // 公共的方法,这里如果是接口就没办法做这种实现了
    protected void commonMethod(){
        bussinessMapper.do();
    }

}
/**
 * 具体策略实现类
 */
@Component
public class ConcreteStrategy1 extends Strategy {
    @Resource
    private BussinessMapper bussinessMapper; // 这里的bussinessMapper一定为空

    @Override
    public void options(DTO dto) {
       // do something
        bussinessMapper.do();
    }
}

解决方案

问题原因

问题就出现在BussinessServiceImpl中,在构造方法中创建了具体策略的实现类,但是new的类并不在Spring的Bean管理中,因此这些类中调用Spring的Bean一定会出现空指针异常。

方案一:使用 @Autowired 注入 Strategy 的实现类

@Service
@Slf4j
public class BussinessServiceImpl implements BussinessService {
    private final Map<Integer, Strategy> strategyMap;

    @Autowired
    public BussinessServiceImpl(ConcreteStrategy1 concreteStrategy1, ConcreteStrategy2 concreteStrategy2) {
        this.strategyMap = new HashMap<>();
        strategyMap.put(1, concreteStrategy1);
        strategyMap.put(2, concreteStrategy2);
    }
}

方案二:使用 @PostConstruct 初始化 strategyMap

@Service
@Slf4j
public class BussinessServiceImpl implements BussinessService {
    private final Map<Integer, Strategy> strategyMap;

    @Autowired
    private ConcreteStrategy1 concreteStrategy1;

    @Autowired
    private ConcreteStrategy2 concreteStrategy2;

    @Autowired
    public BussinessServiceImpl() {
        this.strategyMap = new HashMap<>();
    }

    @PostConstruct
    public void init() {
        strategyMap.put(1, concreteStrategy1);
        strategyMap.put(2, concreteStrategy2);
    }    
}

方案三:使用 @Component@Qualifier

@Service
@Slf4j
public class BussinessServiceImpl implements BussinessService {
    private final Map<Integer, Strategy> strategyMap;

    @Autowired
    public BussinessServiceImpl(@Qualifier("concreteStrategy1") ConcreteStrategy1 concreteStrategy1,
                                @Qualifier("concreteStrategy2") ConcreteStrategy2 concreteStrategy2) {
        this.strategyMap = new HashMap<>();
        strategyMap.put(1, concreteStrategy1);
        strategyMap.put(2, concreteStrategy2);
    }
}
欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇