根据前端传入不同的支付code,动态找到对应的支付方法,发起支付。
我们先定义一个注解。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface PayCode { String value(); String name(); }
在所有的支付类上都加上该注解
@PayCode(value = "alia", name = "支付宝支付") @Service public class AliaPay implements IPay { @Override public void pay() { System.out.println("===发起支付宝支付==="); } } @PayCode(value = "weixin", name = "微信支付") @Service public class WeixinPay implements IPay { @Override public void pay() { System.out.println("===发起微信支付==="); } } @PayCode(value = "jingdong", name = "京东支付") @Service public class JingDongPay implements IPay { @Override public void pay() { System.out.println("===发起京东支付==="); } }
调用
@Service public class PayService2 implements ApplicationListener<ContextRefreshedEvent> { private static Map<String, IPay> payMap = null; @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext(); Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class); if (beansWithAnnotation != null) { payMap = new HashMap<>(); beansWithAnnotation.forEach((key, value) ->{ String bizType = value.getClass().getAnnotation(PayCode.class).value(); payMap.put(bizType, (IPay) value); }); } } public void pay(String code) { payMap.get(code).pay(); } }
PayService2类实现了ApplicationListener接口,这样在onApplicationEvent方法中,就可以拿到ApplicationContext的实例。这一步,其实是在spring容器启动的时候,spring通过反射我们处理好了。
我们再获取打了PayCode注解的类,放到一个map中,map中的key就是PayCode注解中定义的value,跟code参数一致,value是支付类的实例。
这样,每次就可以每次直接通过code获取支付类实例,而不用if...else判断了。如果要加新的支付方法,只需在支付类上面打上PayCode注解定义一个新的code即可。
注意:这种方式的code可以没有业务含义,可以是纯数字,只要不重复就行。