IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring 结合策略模式,如何优雅的实践(普通注入,Map注入,自定义注解注入) -> 正文阅读

[Java知识库]Spring 结合策略模式,如何优雅的实践(普通注入,Map注入,自定义注解注入)

Spring 结合策略模式,如何优雅的实践(普通注入,Map注入,自定义注解注入)

一,认识

掌握注解@Autowired@Resource 基本原理

使用方法

  • @Autowired@Resource注解都是作为bean对象注入的时候使用的。

  • 两者都可以声明在字段和setter方法上

public class  test{
    
    /**字段注入**/
    @Autowired
    private XXXService service;

    /**字段注入**/
    @Resource
    private XXXService service;

    /**构造注入**/
    @Autowired
    public test(XXXService service){
    	this.service = service;
    }
    
 	/**Setter注入**/
    @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

//实现1
@Service
public class Apple implements Fruits {
   @Override
   public void show() {
      System.out.println("我是苹果");
   }
}

实现接口2

//实现2
@Service
public class Banana implements Fruits {
   @Override
   public void show() {
      System.out.println("我是香蕉");
   }
}

创建一个工厂,来实现不同水果

public class IndexMapDataFactory {
     /**使用map,来封装**/	
     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 里面的不同的实现 通过手动注入, 实在不够优雅。接下来我们来升级

使用注解

这里我们来把工厂类改造一下升级一下,变得更加的优雅

/**记为Spring容器中的一个Bean**/
@Slf4j
@Component
public class StrategyFactory {
    
    /**Spring会将实现注入到该map 里面, key:注入的name,默认类名小写, value:为该实例 **/
    @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", "苹果"),
		/**记为Spring容器中的一个Bean**/
        BANANA(2,"banana", "香蕉"),
        
        /**code**/
        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();
    
}

接口实现

//实现1
@FruitsTypeAnnotation(type = "apple")
@Service
public class Apple implements Fruits {
   @Override
   public void show() {
      System.out.println("我是苹果");
   }
}

//实现2
@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));
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:42:45  更:2022-09-24 20:47:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 8:48:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码