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解 ...
随机推荐
- codeforce 1311E. Construct the Binary Tree (构造,就是个模拟)
ACM思维题训练集合 You are given two integers n and d. You need to construct a rooted binary tree consisting ...
- Codeforces Round #622 (Div. 2) 1313 C1
C1. Skyscrapers (easy version) time limit per test1 second memory limit per test512 megabytes inputs ...
- tomcat 在linux下启动时找不到JDK
方案一. 修改bashrc (转载: https://www.cnblogs.com/hongzg1982/articles/2101792.html) $ vim ~/.bashrc #加入JA ...
- vue2.0那些坑之使用elementUI后v-on:click事件不生效问题
最近在维护vue2.0的项目,遇到了不少坑,在这里说下引用elementui之后,使用v-on:click绑定点击事件无效的情况,如下图: 我想阻止冒泡事件,发现无效.这里将@click换成了@cli ...
- P1750 出栈序列
这好像是普及难度的吧~ 感觉再次被小学生吊打了........ \(\color{Red}{----------------------=|(●'◡'●)|=我是手动的分割线------------- ...
- kafka简介及集群部署
消息队列概念:(Message queue): “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象. “消息队列”是在消息的传输过程中保存消 ...
- Spring杂谈 | 什么是ObjectFactory?什么是ObjectProvider?
在Spring的学习过程中,总是学的越多,不懂的越多.本来只是想将ApplicationContext的相关内容全部梳理一遍,结果发现涉及的东西越来越多,比如上篇文章中的ResolvableType, ...
- 201771010113 李婷华 《面向对象程序设计(java)》
一.理论知识部分 设计模式(Design pattern)是设计者一种流行的思考设计问题的方法,是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结.使用设计模式是为了可重用代码.让代码 ...
- 读CSV文件并写arcgis shp文件
一.在这里我用到的csv文件是包含x,y坐标及高程.降雨量数据的文件.如下图所示. 二.SF简介 简单要素模型(Simple Feature,SF),是 OGC 国际组织定义的面向对象的矢量数据模型. ...
- LeetCode--Unique Email Addresses & Hamming Distance (Easy)
929. Unique Email Addresses (Easy)# Every email consists of a local name and a domain name, separate ...