spring设计模式之applicationContext.getBean("beanName")思想
1.背景
在实际开发中我们会经常遇到不同的业务类型对应不同的业务处理,而这个业务类型又是经常变动的;
比如说,我们在做支付业务的时候,可能刚开始需要实现支付宝支付和微信支付,那么代码逻辑可能如下
/**
* 支付选择简易逻辑
*
* @param payType payType zfb-支付宝支付,wx-微信支付
* @param money 需要支付的钱
*/
public void pay(String payType, Double money) {
if ("zfb".equals(payType)) {
System.out.println("=======执行支付宝支付========");
} else if ("wx".equals(payType)) {
System.out.println("=======执行支微信支付========");
} else {
System.out.println("=======支付类型错误========");
}
}
咋一看,这样写也没有什么问题,但是如果因业务需要我们需要增加一个京东支付,那么我们又要else if ().....
如果哪一天我们又要增加一个云闪付支付,那么我们又要else if ().....
如果哪一天我们又要.....................
这样的话,我们这个类会随着这支付类型的变动不断慢慢的扩展和修改....
在修改的过程中甚至将原来的弄错......
最后总结这样的代码违反了开闭原则,好的代码设计思想应该是对修改关闭,对扩展开放;
那么应该如何写呢?
大家可想想象一下,spring的getBean是怎么实现的,
applicationContext.getBean("beanName");
spring在设计的时候并不知道我们后来会写什么bean,它的内部不可能是通过名称 if else 来获取实例对象的,
分析到这里大家有没有感觉到,这里的业务逻辑与我们的支付选择逻辑是相同的,
既然这样,我们是不是可以看一看spring的getBean到是这样实现,如果能大体看懂,是不是我们也可以参照他的思想编写我们的支付逻辑.
2.spring的getBean源码分析
源码跟踪
结论:看到最后,你会发现,spring的实例对象 是根据名称,以key,value的方式放在map中的;
那么,我们的支付逻辑是不是也可以根据支付类型以key-value的方式存放;这样就不会再使用if else.
3.支付业务逻辑实现
1.订单实现类
主要逻辑,
a.在sping启动的时候,通过构造方法或去支付接口的所有实例
b.遍历实例,将实例以key-value的方式放入map
c.在具体支付的时候,通过支付类型从map中获取支付的具体实例,进行支付
package com.example.demo.service.impl; import com.example.demo.service.IOrderService;
import com.example.demo.service.IPayService;
import org.springframework.stereotype.Service; import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* @Copyright (C) XXXXXXXX
* @Author: 姿势帝
* @Date: 2020-05-29 9:56
* @Description:
*/
@Service
public class OrderServiceImpl implements IOrderService {
/**
* 存放支付类型的实例
*/
private Map<String, IPayService> mapPay = new HashMap<>();
/**
* 构造方法
* spring在实例化的时候会将所有的IPayServcie的实例放入list,在通过遍历放入map
*
* @param list
*/
public OrderServiceImpl(List<IPayService> list) {
for (IPayService iPayService : list) {
mapPay.put(iPayService.getPayType(), iPayService);
}
}
/**
* @param payType zfb-支付宝支付,wx-微信支付,ysf-云闪付
* @param money
* @return
*/
@Override
public Object pay(String payType, Double money) {
IPayService payService = mapPay.get(payType);
if (payService == null) {
System.out.println("没有对应的支付方式-->" + payType);
return null;
}
payService.doPay(money);
return null;
}
}
支付接口
package com.example.demo.service; /**
* @Copyright (C) XXXXXXXX
* @Author: 姿势帝
* @Date: 2020-05-29 9:59
* @Description:
*/
public interface IPayService {
/**
* 获取支付类型
* @return
*/
String getPayType(); /**
* 具体支付
* @param money
* @return
*/
Object doPay(Double money);
}
2.支付宝实现类
package com.example.demo.service.impl; import com.example.demo.service.IPayService;
import org.springframework.stereotype.Service; /**
* @Copyright (C) XXXXXXXX
* @Author: 姿势帝
* @Date: 2020-05-29 10:01
* @Description:
*/
@Service
public class PayAliPayServiceImpl implements IPayService {
@Override
public String getPayType() {
return "zfb";
} @Override
public Object doPay(Double money) {
System.out.println("======执行支付宝支付=======money="+money);
return null;
}
}
微信实现类
package com.example.demo.service.impl; import com.example.demo.service.IPayService;
import org.springframework.stereotype.Service; /**
* @Copyright (C) XXXXXXXX
* @Author: 姿势帝
* @Date: 2020-05-29 10:01
* @Description:
*/
@Service
public class PayWechatServiceImpl implements IPayService {
@Override
public String getPayType() {
return "wx";
} @Override
public Object doPay(Double money) {
System.out.println("======执行微信支付=======money="+money);
return null;
}
}
....如果以后有京东,云闪付....等只需要写一个实现类即可,其他代码不需要做任何修改
3.测试
package com.example.demo; import com.example.demo.service.IOrderService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext; @SpringBootTest
class DemoApplicationTests {
@Autowired
private ApplicationContext applicationContext; @Autowired
private IOrderService orderService; /**
* 测试支付
* payType zfb-支付宝支付,wx-微信支付,其他支付....
*/
@Test
void testPay() {
orderService.pay("zfb", 12.89);
} /**
* 获取bean的方法
*/
@Test
public void testBean() {
applicationContext.getBean("beanName");
} /**
* 支付选择简易逻辑
*
* @param payType payType zfb-支付宝支付,wx-微信支付,其他支付....
* @param money 需要支付的钱
*/
public void pay(String payType, Double money) {
if ("zfb".equals(payType)) {
System.out.println("=======执行支付宝支付========");
} else if ("wx".equals(payType)) {
System.out.println("=======执行支微信支付========");
} else {
System.out.println("=======支付类型错误========");
}
} }
完美!
spring设计模式之applicationContext.getBean("beanName")思想的更多相关文章
- 通过ApplicationContext.getBean(beanName)动态加载数据。
一,前台数据 $.ajax({ url: '/intra/coe/order/ploadTable.htm', type: 'POST', dataType: 'json', data: {keyId ...
- spring项目获取ApplicationContext(能手动从Spring获取所需要的bean)
最流行的方法就是 实现ApplicationContextAware接口 @Component public class SpringContextUtil implements Applicati ...
- spring BeanFactory及ApplicationContext中Bean的生命周期
spring bean 的生命周期 spring BeanFactory及ApplicationContext在读取配置文件后.实例化bean前后.设置bean的属性前后这些点都可以通过实现接口添加我 ...
- spring中获取applicationContext
常用的5种获取spring 中bean的方式总结: 方法一:在初始化时保存ApplicationContext对象代码:ApplicationContext ac = new FileSystemXm ...
- 死磕Spring之IoC篇 - Spring 应用上下文 ApplicationContext
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...
- 一) Spring 介绍、IOC控制反转思想与DI依赖注入
一.spring介绍1.IOC反转控制思想(Inversion of Control)与DI依赖注入(Dependency Injection)2.AOP面向切面的编程思想与动态代理3.作用:项目的粘 ...
- springbank 开发日志 一次因为多线程问题导致的applicationContext.getBean()阻塞
几天前遇到的这个问题.由于交易是配置的,不同的交易是同一个类的不同实例,所以不可能提前将其以@autowired类似的方式注入到需要的类中 <op:transaction id="Re ...
- Spring +quartz获取ApplicationContext上下文
job存在数据库中,能够进行动态的增增删改查,近期遇到了怎样获取ApplicationContext上下文的问题.解决的方法例如以下 applicationContext-quartz.xml < ...
- Spring注解--实现applicationContext.xml效果
随着越来越多地使用Springboot敏捷开发,更多地使用注解配置Spring,而不是Spring的applicationContext.xml文件. Configuration注解: Spring解 ...
随机推荐
- USACO Training Section 1.2 [USACO1.2]回文平方数
题目描述 回文数是指从左向右念和从右向左念都一样的数.如12321就是一个典型的回文数. 给定一个进制B(2<=B<=20,由十进制表示),输出所有的大于等于1小于等于300(十进制下)且 ...
- 图论--差分约束--POJ 1364 King
Description Once, in one kingdom, there was a queen and that queen was expecting a baby. The queen p ...
- P1458 顺序的分数 Ordered Fractions(有技巧的枚举)+C++类封装=精简代码
题目描述 输入一个自然数N,对于一个最简分数a/b(分子和分母互质的分数),满足1<=b<=N,0<=a/b<=1,请找出所有满足条件的分数. 这有一个例子,当N=5时,所有解 ...
- dos命令下安装pip报错 不是内部命令
在dos命令下: pip install requests 遇到这种情况一般是Python的环境变量没有设置好 解决方案一:设置环境变量 C:\Python\scripts 如图 是否有pytho ...
- Android原生多语言切换方案,兼容Android10
前言 一个应用若需要国际化,至少需要支持中文和英语这两种语言,而同时随着谷歌的系统的更新,安卓系统可以设置当前语言的首选语言.因此,本文立足于此,多语言的切换方案为:App固定的文字内容,跟随系统,中 ...
- Edge Weight Assignment(树-异或-贪心)
大意: 给定一棵无根树,要求你任意设置n-1条边的边权. 使得任意叶子节点间边权的XOR值为0: 此时,令f为所有边权数值不同的个数,求最小的f和最大的f. \(\color{Red}{------- ...
- 正方形已知两点对角线求另外两点(POJ2002)
至于为什么,上图.转载于MZW_BG 枚举正方形的一条边,此时有上正方形和下正方形. 最后正方形个数/4,因为每个正方形被枚举了4条边 #include <bits/stdc++.h> u ...
- kafka学习 之 Quickstart
第一步:安装启动kafka 官网链接:https://www.apache.org/dyn/closer.cgi?path=/kafka/2.3.0/kafka_2.11-2.3.0.tgz 进入指定 ...
- boost在Qt中的使用
一.说明 理论上,Qt和boost是同等级别的C++库,如果使用Qt,一般不会需要再用boost,但是偶尔也会有特殊情况,比如,第三方库依赖等等.本文主要介绍boost在windows Qt(MinG ...
- 高性能mysql第三版读书笔记3
innodb以前不支持高并发,在搞病房下就是悲剧,全部卡在mutex(缓冲池mutex)上,现在通过线程调度器控制线程怎么进入内核访问数据,参数为innodb_thread_concurrency,它 ...