使用自定義注解動態綁定多實現類實例


  摘要: 由於業務場景復雜,一個算法需要開發行為變化多端的多個實現類,然后在系統運行時根據不同場景裝載不同的類實例。為了使源碼具有更好的可擴展性和可重用性,在借鑒前人處理方法的基礎上,介紹在Spring項目中,基於自定義注解實現動態匹配相關實現類示例,並調用其中的函數。

前言

  在博文《Spring注解之自定義注解入門》中,介紹了如何使用Spring提供的元注解定義新注解的基本語法,本文在此基礎之上介紹如何使用自定義注解動態匹配相關實現類實例,並調用其中的函數。

  欲了解更多相關知識點請移步《Spring 動態綁定多實現類實例綜述》。

業務場景回顧

  需求描述:定制一個繪圖工具,她根據客戶端發送的指令可以畫出正方形、矩形、圓形和三角形等各種各樣的幾何圖形。例如,當客戶端需要繪制三角形的時候,就調用繪制三角形的方法;當需要繪制圓形的時候,就調用繪制圓形的方法。

  話不多說,直接上代碼,我們首先創建自定義注解ShapeAn:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定義畫圖注解
 *
 * @author Wiener
 * @date 2021/1/30
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ShapeAn {
    String value();
    String beanName();
}

  其中包含兩個成員變量實現類bean昵稱value和bean的中文名稱 beanName。給每個接口類Shape的實現類添加自定義注解:

import com.eg.wiener.config.ShapeAn;
import com.eg.wiener.service.Shape;
import org.springframework.stereotype.Service;

/**
 * 三角形
 *
 * @author Wiener
 * @date 2021/1/7
 */
@ShapeAn(value = "triangleAn", beanName = "三角形畫圖工具")
@Service
public class Triangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Triangle::draw() method.");
    }
}
// ---我是分割線---

import com.eg.wiener.config.ShapeAn;
import com.eg.wiener.service.Shape;
import org.springframework.stereotype.Service;

/**
 * 正方形
 *
 * @author Wiener
 * @date 2021/1/7
 */
@ShapeAn(value = "squareAn", beanName = "正方形畫圖工具")
@Service
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Square::draw() method.");
    }
}
// ---我是分割線---
import com.eg.wiener.config.ShapeAn;
import com.eg.wiener.service.Shape;
import org.springframework.stereotype.Service;

/**
 * 矩形
 *
 * @author Wiener
 * @date 2021/1/7
 */
@ShapeAn(value = "rectangleAn", beanName = "矩形畫圖工具")
@Service
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}

// ---我是分割線---

import com.eg.wiener.config.ShapeAn;
import com.eg.wiener.service.Shape;
import org.springframework.stereotype.Service;

/**
 * 圓形畫圖實現類
 *
 * @author Wiener
 * @date 2021/1/7
 */
@ShapeAn(value = "circleAn", beanName = "圓形畫圖工具")
@Service
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

  通過函數getBeansWithAnnotation(Class<? extends Annotation> annotationType)獲取所有使用了自定義注解的bean:


import com.eg.wiener.config.ShapeAn;
import com.eg.wiener.service.Shape;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 自定義注解實現畫圖工具類自動識別
 *
 * @author Wiener
 * @date 2021/1/19
 */
@Component
public class ShapeServiceAnnotation implements ApplicationListener<ContextRefreshedEvent> {

    private static Map<String, Shape> shapeMap = null;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext ac = contextRefreshedEvent.getApplicationContext();
        Map<String, Object> beansWithAnnotation = ac.getBeansWithAnnotation(ShapeAn.class);
        if (beansWithAnnotation != null) {
            shapeMap = new HashMap<>();
            beansWithAnnotation.forEach((key, value) ->{
                String bizType = value.getClass().getAnnotation(ShapeAn.class).value();
                shapeMap.put(bizType, (Shape) value);
            });
        }
    }
    public void draw(String bean) {
        shapeMap.get(bean).draw();
    }
}

  在控制層創建測試方法:

    @Autowired
    private ShapeServiceAnnotation shapeServiceAnnotation;
	
    /**
     * xxx/drawByAnno?code=rectangleTem
     * 由自定義注解實現
     * @param code 實現類bean名稱
     * @return
     */
    @GetMapping("/drawByAnno")
    public String drawByAnno(String code) {
        shapeServiceAnnotation.draw(code);
        return "由自定義注解實現Bean裝配成功";
    }

  我們只需要在客戶端向函數 drawByAnno(String code)傳入約定的入參rectangle和circle等即可完成方法調用。

結束語

  一個接口由於場景不同,導致需要開發不同的實現類。本文介紹在Spring Boot項目中,基於自定義注解實現動態匹配相關實現類示例,並調用其中的函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM