Fork me on GitHub

springboot使用自定义注解和反射实现一个简单的支付

 

 

优点:

未使用if else,就算以后增加支付类型,也不用改动之前代码

只需要新写一个支付类,给添加自定义注解@Pay

 

首先:

定义自定义注解 Pay

定义 CMBPay ICBCPay 两种支付 根据注解中的value 标识是哪种支付(1为CMBPay  2为ICBCPay)

两种支付都需继承InitNewService.java 避免注入对象报错

 

package com.huarui.inter;

import java.math.BigDecimal;

/**
 * 支付需实现该接口
 * 接口编程:
 */
public interface Strategy {

    /**
     * 计算支付金额 通过渠道id和商品id 进行价格计算
     * @param channelId
     * @param goodsId
     * @return
     */
    BigDecimal calRecharge(Integer channelId,Integer goodsId);

} 

 

package com.huarui.pay;

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) //生命周期
public @interface Pay {

    int value();

} 
@Pay(2)
public class ICBCPay extends InitNewService implements Strategy {
    
    @Override
    public BigDecimal calRecharge(Integer channelId, Integer goodsId) {
        //通过渠道id查询优惠折扣

        //通过商品id查询商品价格

        //返回商品最终价格
        return new BigDecimal(100);
    }
}
ICBCPay.java
package com.huarui.pay;

import com.huarui.inter.Strategy;
import com.huarui.util.CommonUtil;
import com.huarui.util.InitNewService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;

@Pay(1)
public class CMBPay extends InitNewService implements Strategy {

    @Autowired
    private CommonUtil commonUtil;

    @Override
    public BigDecimal calRecharge(Integer channelId, Integer goodsId) {
        //通过渠道id查询优惠折扣

        //通过商品id查询商品价格

        System.out.println(commonUtil.injectStr());

        //返回商品最终价格
        return new BigDecimal(100);
    }
}
CMBPay.java

 

package com.huarui.factory;

import com.huarui.inter.Strategy;
import com.huarui.pay.Pay;
import org.reflections.Reflections;

import java.util.HashMap;
import java.util.Set;

/**
 * 【工厂类】
 * 通过指定扫码路径读取带有自定义注解Pay的类
 * <br>并将全类名保存至map中,格式为["pay的value":"类的全类名"]
 * <br> 定义了creator方法,传入支付类型 返回 指定支付对象
 */
public class StrategyFactory {


    private static StrategyFactory factory = new StrategyFactory();

    /**
     * 单例
     * @return
     */
    public static StrategyFactory getInstance(){
        return factory;
    }

    public static HashMap<Integer,String> sourceMap = new HashMap<>();

    static {

        //反射工具包,指明扫描路径
        Reflections reflections = new Reflections("com.huarui.pay");
        //获取带我们pay注解的类
        Set<Class<?>> classSet =  reflections.getTypesAnnotatedWith(Pay.class);
        //根据注解的值,将全类名放到map中
        for (Class clazz : classSet){
            Pay pay = (Pay) clazz.getAnnotation(Pay.class);
            sourceMap.put(pay.value(),clazz.getCanonicalName());
        }

    }

    public Strategy creator(int type) throws Exception {
        //取得全类名
        String className = sourceMap.get(type);
        //取得类对象
        Class  clazz= Class.forName(className);
        //反射创建对象
        return (Strategy) clazz.newInstance();
    }

} 
package com.huarui.inter;

import com.huarui.factory.StrategyFactory;

import java.math.BigDecimal;

public class Context {

    /**
     *
     * @param channelId 支付类型id
     * @param goodsId   商品id
     * @return
     * @throws Exception
     */
    public BigDecimal calRecharge(Integer channelId,Integer goodsId) throws Exception {
        Strategy strategy = StrategyFactory.getInstance().creator(channelId);
        return strategy.calRecharge(channelId,goodsId);
    }
} 

 

junit测试类

 

 

package com.huarui;

import com.huarui.inter.Context;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.math.BigDecimal;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SbCodeApplicationTests {

    @Test
    public void contextLoads() throws Exception {

        Context context = new Context();
        BigDecimal bigDecimal = context.calRecharge(1,500);
        System.out.println(bigDecimal);

    }

}

 

项目结构:

 

源码地址: https://github.com/youxiu326/sb_code

 

posted @ 2019-07-12 09:56  youxiu326  阅读(1481)  评论(0编辑  收藏  举报