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); } }
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); } }
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