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解 ...
随机推荐
- 数学--数论--HDU1222 狼和兔子(最大公约数)
问题描述 有一座周围有n个洞的小山.孔从0到n-1有符号. 兔子必须藏在其中一个洞中.狼以逆时针方向搜索兔子.他第一个进入的洞是一个用0签名的洞.然后,他将每m个洞进入一个洞.例如,m = 2和n = ...
- .Net Core中使用Dapper构建泛型仓储
前言:Dapper是.NET的简单对象映射器,在速度方面拥有ORM之王的称号,与使用原始ADO.NET读取数据一样快.ORM是对象关系映射器,它负责数据库和编程语言之间的映射. 仓储主要是用来解耦业务 ...
- kafka-eagle监控kafka
最近想做一个kafka监控,本来准备用zabbix来监控的,需要重复造轮子,本来准备用kafka-Manager的,在GitHub上无意发现了kafka-eagle,看了官方介绍准备试一下..... ...
- 【Java8新特性】Lambda表达式基础语法,都在这儿了!!
写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...
- shell字符串索引
shell中的字符串索引一会从0开始,一会从1开始,见例子: #!/bin/bash string="hello world" length=${#string} echo &qu ...
- spring mvc从后台往前台传参数的三种方式
第一种:使用Model对象(常用) 第一步:使用model对象往前台传递数据 第二步:在jsp中接收从后台传递过来的参数 第二种:使用HttpServletRequest对象 第一步:使用HttpSe ...
- zabbix 告警信息与恢复信息
名称: Action-Email 默认接收人: 故障{TRIGGER.STATUS},服务器:{HOSTNAME1}发生: {TRIGGER.NAME}故障! 默认信息: 告警主机:{HOSTNAME ...
- OpenCV之Mat类使用总结
#前言 Mat 是Opencv中很常用的一个图像容器类,图像在计算机中的存储形式是二进制字节流,其本质的存储形式如下图所示: 而一张图片是由很多像素点组成,单个像素点又会因为图像格式的不同而不同.例如 ...
- quartus ii FFT核使用
quartus ii FFT核使用 导入自己程序自带的txt文件,写出控制模块 时序图 FFT核文件给出的时序图输入 仿真时序图 1024个采样点数,输入结束 fft数据输出 2.代码 `timesc ...
- Altium Designer PCB封装bug,元件焊盘位置偏移解决方法
1.问题描述:在拖动几个电阻位置时,意外发现Altium designer20版本软件的一个bug——0805的电阻两焊盘位置发生了偏移,如下图所示. 2.解决办法: ①选中焊盘偏移的封装,右键剪切掉 ...