前言
策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在spring框架中,我们可以利用@resource
注解和map
集合来优雅地实现策略模式。
在spring框架中,当你使用@resource
注解注入一个map<string, t>
时,spring会自动将所有类型为t的bean收集到这个map中,其中:
- key是bean的名称
- value是bean实例
底层机制解析
spring的集合类型自动装配
spring框架对集合类型的依赖注入有特殊处理:
- 当注入list时,会收集所有类型为t的bean
- 当注入map<string, t>时,会收集所有类型为t的bean,并以bean名称作为key
@resource注解的行为
@resource
注解默认按名称装配,但当目标是一个map时,spring会特殊处理:
- 如果map的key是string类型,value是某个接口/类
- spring会查找所有实现该接口/继承该类的bean
- 将这些bean以"bean名称->bean实例"的形式放入map
实现原理
spring在依赖注入时的处理流程:
- 发现字段/方法参数是map<string, t>类型
- 在应用上下文中查找所有类型为t的bean
- 创建一个新的map实例
- 遍历找到的所有bean,以bean名称作为key,bean实例作为value放入map
- 将这个map注入到目标字段/参数中
使用
直接使用map<string,t>
我们直接定义一个controller,并且在controller中使用@resource
和map<string,t>
@restcontroller @requestmapping("/test") public class testcontroller { @resource private map<string, object> beanmap = new concurrenthashmap<>(); public void beanmap() { system.out.println(beanmap.size()); } }
验证:可以看到map中存了项目中所有的bean对象
指定map中的bean类型
在实际的开发中,我们希望map中只是存储需要的bean,并且controller中可以根据beanname进行转发到不同的service中,步骤如下:
定义策略接口
public interface paymentstrategy { void pay(); }
定义实现类
@service("ali") @slf4j public class alistrategyservice implements paymentstrategy { @override public void pay() { log.info("使用支付宝支付"); } } @service("wx") @slf4j public class wxstrategyservice implements paymentstrategy { @override public void pay() { log.info("使用微信支付"); } }
策略使用
@restcontroller @requestmapping("/test") public class testcontroller { @resource private map<string, paymentstrategy> beanmap = new concurrenthashmap<>(); public void beanmap() { paymentstrategy wx = beanmap.get("wx"); wx.pay(); paymentstrategy ali = beanmap.get("ali"); ali.pay(); } }
验证
可以看到map中,就只有两个bean,并且key就是我们通过@service(value)定义的名称
自定义注解实现
自定义一个注解
import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; import java.lang.annotation.target; @target({elementtype.type}) @retention(retentionpolicy.runtime) @component public @interface paymenttype { string value(); }
注解替换:将原有的@service(value)
替换为@paymenttype (value)
,比如:
@paymenttype("card") @slf4j public class cardstrategyservice implements paymentstrategy { @override public void pay() { log.info("使用银行卡支付"); } }
**意义:**可以更好表示策略模式,让其他开发人员一眼可以看出当前的service
使用了策略模式
到此这篇关于springboot通过map实现天然的策略模式的文章就介绍到这了,更多相关springboot策略模式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论