Spring 结合策略模式,如何优雅的实践(普通注入,Map注入,自定义注解注入)
一,认识
掌握注解@Autowired 和 @Resource 基本原理
使用方法
public class test{
@Autowired
private XXXService service;
@Resource
private XXXService service;
@Autowired
public test(XXXService service){
this.service = service;
}
@Autowired
public void setService(XXXService service) {
this.service = service;
}
}
以上三种使用方式 字段注入,构造注入,setter注入。
区别:
-
@Autowired 注解是Spring 提供的,而@Resource 注解是J2EE 本身提供的 -
@Autowird 注解默认通过byType 方式注入,而@Resource 注解默认通过byName 方式注入 -
@Autowired 注解注入的对象需要在IOC 容器中存在,否则需要加上属性required =false ,表示忽略当前要注入的bean ,如果有直接注入,没有跳过,不会报错
其他源码不再撰述,可以自行查看网上相关资料。
掌握策略模式
不了解原理的,可以看我之前写的设计模式,策略博客:地址轻点跳转:https://blog.csdn.net/Crazy_Cw/article/details/106818217
二,实现策略模式
简单通过手动注入bean实现策略模式
定义一个父类接口
public interface Fruits{
void show();
}
实现接口1
@Service
public class Apple implements Fruits {
@Override
public void show() {
System.out.println("我是苹果");
}
}
实现接口2
@Service
public class Banana implements Fruits {
@Override
public void show() {
System.out.println("我是香蕉");
}
}
创建一个工厂,来实现不同水果
public class IndexMapDataFactory {
private static final Map<Integer, Fruits> MAP_DATA = Maps.newHashMap();
private static final Apple service1 = SpringUtil.getBean(Apple.class);
private static final Banana service2 = SpringUtil.getBean(Banana.class);
static {
MAP_DATA.put(0, service1);
MAP_DATA.put(1, service2);
}
public static Fruits getServiceByType(int type) {
return MAP_DATA.get(type);
}
}
我们这里看到工厂类IndexMapDataFactory 里面的不同的实现 通过手动注入, 实在不够优雅。接下来我们来升级
使用注解
这里我们来把工厂类改造一下升级一下,变得更加的优雅
@Slf4j
@Component
public class StrategyFactory {
@Resource
private Map<String, Fruits> interFaceMap;
public Fruits getServiceByType(Integer code) {
String implementName = FruitsTypeEnum.getImplementByCode(code);
Fruits bean = interFaceMap.get(implementName);
if(bean == null){
log.error("策略工厂bean异常:{} bean is null",implementName);
throw new RuntimeException("bean is null");
}
return bean;
}
public enum FruitsTypeEnum {
APPLE(1,"apple", "苹果"),
BANANA(2,"banana", "香蕉"),
public Integer code;
public String implement;
public String desc;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getImplement() {
return implement;
}
public void setImplement(String implement) {
this.implement = implement;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
FruitsTypeEnum(Integer code, String implement, String desc) {
this.code = code;
this.implement = implement;
this.desc = desc;
}
public static String getImplementByCode(Integer code) {
for (FruitsTypeEnum value : FruitsTypeEnum.values()) {
if (value.getCode().equals(value.getCode())) {
return value.getImplement();
}
}
return null;
}
}
}
使用
public void Controller {
@Resource
StrategyFactory strategyFactory;
public void test(int code){
Fruits fruits = strategyFactory.getServiceByType(code);
fruits.show();
}
}
自定义注解,来优雅实现策略模式
自定义注解
import com.hong.strategy.enums.OrderTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface FruitsTypeAnnotation {
String fruitsType();
}
接口实现
@FruitsTypeAnnotation(type = "apple")
@Service
public class Apple implements Fruits {
@Override
public void show() {
System.out.println("我是苹果");
}
}
@FruitsTypeAnnotation(type = "banana")
@Service
public class Banana implements Fruits {
@Override
public void show() {
System.out.println("我是香蕉");
}
}
一个水果品种实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Type {
private String name;
}
向spring容器中注入
@Component
public class StrategyFactory {
private Map<String, Fruits> map;
@Autowired
public void setMap(List<Fruits> fruitsInterfaces) {
map = fruitsInterfaces.stream().collect(
Collectors.toMap(t -> AnnotationUtils.findAnnotation(t.getClass(), FruitsTypeAnnotation.class).type(),
v -> v, (v1, v2) -> v1));
}
public void fruitsService(List<Type> list){
list.forEach(t->{
Fruits fruits = map.get(t.getName());
fruits.show();
});
}
}
测试
@Autowired
private StrategyFactory strategyFactory;
@Test
void test(){
Type apple = new Type("apple");
Type banana = new Type("banana");
strategyFactory.fruitsService(Arrays.asList(apple,banana));
}
|