1.为什么要进行service层的封装?

业务逻辑无非增删改查,如果针对与单表的增删改查很多,这时候,我们如果不封装,在service层会有很多的重复代码,

就像下图一样,除了mapper不同,其余一模一样,这时候 我们会考虑,把他放在父类完成,

2. 那么如何将这个方案落地呢?

1.首先,我们需要让父类先获得一个mapper

解决方案:1. 父类定义一个 成员变量 类型为泛型,具体类型由子类决定

2. 获取泛型的类型(考虑到可能有多个泛型,我们这里获取第一个)

(Class<Mapper>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

3.根据泛型的类型,获取bean

this.mapper = SpringContextUtil.getBean(getMapperClass())

2.其次,使用 mapper调用相应的方法

问题:不知道mapper类型的情况下,调用其方法

解决方案:  1.统一mapper中方法的的名称,(如果dao层通过 mybatis逆向工程生成,无需考虑这个问题)

2.通过反射调用其方法

Method deleteByExample = mapper.getClass().getDeclaredMethod("deleteByExample", example.getClass());
                                        Object result = deleteByExample.invoke(mapper, example);

3.最后的类层次结构

4,talk is cheap ,show me the code.

public class CmsCommentServiceImpl extends BaseServiceImpl<CmsCommentMapper, CmsComment, CmsCommentExample> implements CmsCommentService {private static final Logger LOGGER = LoggerFactory.getLogger(CmsCommentServiceImpl.class);@AutowiredCmsCommentMapper cmsCommentMapper;}
public abstract class BaseServiceImpl<Mapper, Record, Example> implements BaseService<Record, Example> {public Mapper mapper;@Overridepublic int deleteByExample(Example example) {try {DynamicDataSource.setDataSource(DataSourceEnum.MASTER.getName());Method deleteByExample = mapper.getClass().getDeclaredMethod("deleteByExample", example.getClass());Object result = deleteByExample.invoke(mapper, example);return Integer.parseInt(String.valueOf(result));} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}DynamicDataSource.clearDataSource();return 0;}/***需要配置一个监听器调用*/@Overridepublic void initMapper() {this.mapper = SpringBeanFactoryUtils.getBean(getMapperClass());}/*** 获取类泛型class* @return*/public Class<Mapper> getMapperClass() {return (Class<Mapper>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];}
}
public interface BaseService<Record, Example> {/*** 根据条件删除记录* @param example* @return*/int deleteByExample(Example example);
}
/*** spring容器初始化完成事件* Created by shuzheng on 2017/1/7.*/
public class ApplicationContextListener implements ApplicationListener<ContextRefreshedEvent> {private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContextListener.class);@Overridepublic void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {// root application contextif(null == contextRefreshedEvent.getApplicationContext().getParent()) {LOGGER.debug(">>>>> spring初始化完毕 <<<<<");// spring初始化完毕后,通过反射调用所有使用BaseService注解的initMapper方法Map<String, Object> baseServices = contextRefreshedEvent.getApplicationContext().getBeansWithAnnotation(BaseService.class);for(Object service : baseServices.values()) {LOGGER.debug(">>>>> {}.initMapper()", service.getClass().getName());try {Method initMapper = service.getClass().getMethod("initMapper");initMapper.invoke(service);} catch (Exception e) {LOGGER.error("初始化BaseService的initMapper方法异常", e);e.printStackTrace();}}
}
}
@Component
public class SpringBeanFactoryUtils implements ApplicationContextAware {private static ApplicationContext context = null;public static <T> T getBean(Class<T> type) {return context.getBean(type);}public static <T> T getBean(String name, Class<T> type) {return context.getBean(name, type);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.err.println("SpringBeanFactoryUtils be inited...");if (SpringBeanFactoryUtils.context == null) {SpringBeanFactoryUtils.context=applicationContext;}}
}

5.剩余问题

1.多数据源切换( 测试通过)

2.多数据源事务问题(测试通过)

service层的封装相关推荐

  1. Spring Boot神操作-多个数据源Service层封装

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:@pdai pdai.tech/md/spring/spri ...

  2. Spring Boot骚操作-多数据源Service层封装

    原文:https://www.pdai.tech/md/spring/springboot-data-multi.html mysql, es, mongodb 三个数据源用配置文件方式连接,JPA只 ...

  3. DAO层,Service层,Controller层的作用

    DAO层: DAO层主要是做数据持久层的工作,用来对应数据库实体,负责与数据库进行联络的一些任务都封装在此.主要就是封装一些数据库的增删改查操作,但仅仅是封装了操作,具体的实现并不在dao层里,所以我 ...

  4. service层的作用

    一直不太明白service层的作用,有时候甚至感觉service层可有可无. dao层中已经有操作数据库的方法了,为什么还要service层去封装?有什么好处? 首先是mvc三层架构 mvc三层架构 ...

  5. java action dao_java中Action层、Service层和Dao层的功能区分

    一.Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DA ...

  6. [转]JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分

    首先这是现在最基本的分层方式,结合了SSH架构.modle层就是对应的数据库表的实体类.Dao层是使用了Hibernate连接数据库.操作数据库(增删改查).Service层:引用对应的Dao数据库操 ...

  7. java domain层_java框架中的controller层、dao层、domain层、service层、view层

    1.Controller层:接口层,用户访问请求时对接. Controller层负责具体的业务模块流程的控制,在此层里面要调用Serice层的接口来控制业务流程,控制的配置也同样是在Spring的配置 ...

  8. Java Web学习总结(30)——Service层在MVC框架中的意义和职责

    mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层设计, ...

  9. 一步一步搭架子(DM层与Service层)

    首先分享一点自己最近的感悟:讨厌你的人总可以找到理由去讨厌你 正文开始 如果您是初次阅读这个系列,请先去<Index & Writing Plan>查找并阅读"架构设计系 ...

最新文章

  1. mstsc VS vnc : 远程桌面最快的原因在于RDP协议
  2. 王者荣耀服务器维护啥意思,王者荣耀
  3. Oracle中Cursor介绍
  4. python分词和词频统计
  5. WinXP下替代IIS的新思路
  6. golang切片转为字符串,字符串转切片
  7. 查看pod网络范围_K8S Pod 内抓包快速定位网络问题
  8. 为什么程序员纷纷反对微软收购GitHub?
  9. 美媒:中国可能引领“物联网”的进步
  10. 使用paramiko在eNSP的交换机中批量创建VLAN
  11. php 点击菜单栏只刷新局部,layui点击左侧导航栏,实现不刷新整个页面,只刷新局部的方法...
  12. python中raise stoplteration_Python 中的异常处理
  13. python的输出语句_python 中简单的输出语句
  14. wps linux2019特色功能,WPS Office 2019 For Linux更新至11.1.0.9522版,附新功能介绍
  15. DS18B20温度传感器-51单片机控制程序
  16. Tomcat控制台弱密码漏洞
  17. ubuntu18下成功安装Remastersys备份当前系统成ISO文件
  18. cim系统(cim系统包含哪些部分)
  19. dos批处理脚本自动添加网络IP打印机-简单亲测可用
  20. 本地安装青龙面板教程【详细版】2022-5.5

热门文章

  1. Asp.net利用CommandArgument传值
  2. php 创建图像不成功,php 创建图像不成功怎么办
  3. 下载mysql.ios_iMySqlProg ios版下载_iMySqlProg苹果版
  4. 服务器保存数据的文件,服务器数据怎么保存
  5. 女生计算机软件还是硬件,对于女生来说,计算机专业选软件好呢,还是硬件?...
  6. 王传福称华为手机是比亚迪造的;贝索斯将于7月20日飞往太空;苹果泄露女生私密照赔偿数百万美元 | EA周报...
  7. hadoop生态圈学习总结
  8. python-sklearn岭回归与LASSO回归模型(套索)代码实操
  9. c语言 英文歌曲大赛,实验部第一届英文歌曲大赛
  10. StrictMode引发的惨案