【Spring源码解析】—— 委派模式的理解和使用
一、什么是委派模式
委派模式,是指什么呢?从字面含义理解,委派就是委托安排的意思,委派模式就是在做具体某件事情的过程中,交给其他人来做,这个事件就是在我的完整链路上的一部分,但是复杂度较高的情况下或者我不想做的情况下,完全可以委派给另一个类来处理,只要这个结果是符合我的预期的就可以(相当于填空)。
模板模式与委派模式的区别:模板模式更关注步骤,公共部分会放在模板的骨架步骤中完成,针对子类可能会有特殊的一些操作就可以在特定步骤中重新实现,从模板模式中能够看到清晰的过程步骤。
代理模式与委派模式的区别:代理模式就是这个事情就根本不是我做的,但是我只能提供其中关键的一些信息,其他的周边或者在此基础上的扩展都可以交给其他人来做,完整的一个问题,能够得到解决(这是目前理解到的代理模式,后续如果有更新,会重新对这里进行修改)
二、Spring中的应用
(一) iOC相关部分中,在进行对象实例化的过程有用到委派模式?
在doRegisterBeanDefinitions()即BeanDefinition进行注册的过程中,会设置BeanDefinitionParserDelegate类型的Delegate对象传给this.delegate,并将这个对象作为一个参数传给:parseBeanDefinitions(root, this.delegate)中,然后主要的解析的工作就是通过delegate作为主要角色来完成的,可以看到下方代码:
/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
* @param root the DOM root element of the document
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//判断节点是否属于同一命名空间,是则执行后续的解析
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
//注解定义的Context的nameSpace进入到这个分支中
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
其中最终能够走到bean注册部分的是,会进入到parseDefaultElement(ele, delegate)中,然后针对不同的节点类型,针对bean的节点进行真正的注册操作,而在这个过程中,delegate会对element进行parseBeanDefinitionElement,得到了一个BeanDefinitionHolder类型的对象,之后通过这个对象完成真正的注册到Factory的操作
(二) 在SpringMVC中,类DispatcherServlet,就是:用于HTTP请求处理程序/控制器的中央调度程序,针对通过WEB UI输入的url请求,委派给DispatcherServlet处理,从委派者的角度来看,关注结果即可
(三) 实际生活的例子:委派可以理解成Leader来做工作,也会做一部分,只是将其中一个部分交给Member来做,Member按照自己的方式做完之后,Leader只关注结果(这是一个两方的关系,代理模式是一个三方的关系,例如房东+中介+租客,中介相对于房东和租客来说,都是代理)。
三、自写demo示例
分别为:Leader类、Member类、StaffdoTask类、StaffInfo类、Task类
其中Task类为:任务类;StaffInfo类:雇员信息类;StaffdoTask类:雇员做任务类;Leader类:组长类(委派者),Member类:组员类(被委派者)
Task类代码如下:
public class Task {
String id;
String name;
String step;
String deadline;
public Task(String id, String name, String step, String deadline) {
this.id = id;
this.name = name;
this.step = step;
this.deadline = deadline;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDeadline() {
return deadline;
}
public String getStep() {
return step;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDeadline(String deadline) {
this.deadline = deadline;
}
public void setStep(String step) {
this.step = step;
}
}
StaffInfo类:
public class StaffInfo {
String staffid;
String staffname;
public StaffInfo(String staffid, String staffname) {
this.staffid = staffid;
this.staffname = staffname;
}
public String getStaffid() {
return staffid;
}
public void setStaffid(String staffid) {
this.staffid = staffid;
}
public String getStaffname() {
return staffname;
}
public void setStaffname(String staffname) {
this.staffname = staffname;
}
}
StaffdoTask接口,Leader类和Member类实现了该接口
public interface StaffdoTask {
public void doTask(StaffInfo staffInfo, Task task);
}
Leader类:
public class Leader{
//假设Leader的角色为区域销售主管,针对店铺进行人员盘点,将A人员分配到1区,将B人员分配到2区
//店长需要针对区域进行整体管理,包含人员的考勤、日常管理和工作访谈、人员培养等
//其中销售的工作给到不同的区的人员主负责
public void doTask() {
Task task_gongzuofangtan = new Task("1", "工作访谈",
"1、跟进每个区的工作负责人,2、进行访谈交流,3、汇总结果", "20190823");
Task task_kaoqin = new Task("2", "考勤管理", "1、查看每日每人的考勤情况,2、输出考勤报表",
"20190823");
Task[] task_xiaoshou = new Task[3];
Task xiaoshou_1 = new Task("3", "销售", "1、A区域内的人员出售车辆", "2019-0824");
Task xiaoshou_2 = new Task("3", "销售", "1、B区域内的人员出售车辆", "2019-0824");
Task xiaoshou_3 = new Task("3", "销售", "1、C区域内的人员出售车辆", "2019-0824");
task_xiaoshou[0] = xiaoshou_1;
task_xiaoshou[1] = xiaoshou_2;
task_xiaoshou[2] = xiaoshou_3;
Task task_huizong = new Task("4", "汇总", "1、将各个区的工作进行整理,2、汇总输出报告", "20190826");
//做自己的工作
doRealTask(task_gongzuofangtan);
doRealTask(task_kaoqin);
StaffInfo[] staff_xiaoshou = new StaffInfo[3];
StaffInfo staff_1 = new StaffInfo("1023", "A");
StaffInfo staff_2 = new StaffInfo("1024", "B");
StaffInfo staff_3 = new StaffInfo("1025", "C");
staff_xiaoshou[0] = staff_1;
staff_xiaoshou[1] = staff_2;
staff_xiaoshou[2] = staff_3;
doDispatcherTask(task_xiaoshou, staff_xiaoshou);
doRealTask(task_huizong);
}
public void doRealTask(Task task){
// System.out.println("task info");
System.out.println("taskid:" + task.id + " taskname:" + task.name +
" taskstep:" + task.step + " taskdeadline:" + task.deadline);
}
//Desc:进行任务分发处理
public void doDispatcherTask(Task[] tasks, StaffInfo[] staffInfos){
System.out.println("做销售任务的委派");
for (int i = 0; i < tasks.length; i++){
Member member = new Member();
member.doTask(staffInfos[i], tasks[i]);
}
}
public static void main(String[] args){
System.out.println("开始工作,并做好任务分派");
Leader leader = new Leader();
leader.doTask();
}
}
Member类:
public class Member implements StaffdoTask{
@Override
public void doTask(StaffInfo staffInfo, Task task) {
System.out.println("statff " + staffInfo.staffid + "do the task:" + task.id + " " +task.name
+ " " + task.step + " " + task.deadline);
}
}
其中Leader类的main代码运行之后,结果如下:

【Spring源码解析】—— 委派模式的理解和使用的更多相关文章
- Spring源码解析 - AbstractBeanFactory 实现接口与父类分析
我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...
- spring 源码解析
1. [文件] spring源码.txt ~ 15B 下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB 下载( ...
- Spring源码解析——循环依赖的解决方案
一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...
- Spring源码解析之ConfigurationClassPostProcessor(二)
上一个章节,笔者向大家介绍了spring是如何来过滤配置类的,下面我们来看看在过滤出配置类后,spring是如何来解析配置类的.首先过滤出来的配置类会存放在configCandidates列表, 在代 ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
- Spring源码解析-ioc容器的设计
Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...
- Spring源码解析系列汇总
相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...
- Spring源码解析之PropertyPlaceholderHelper(占位符解析器)
Spring源码解析之PropertyPlaceholderHelper(占位符解析器) https://blog.csdn.net/weixin_39471249/article/details/7 ...
- Spring源码解析之BeanFactoryPostProcessor(三)
在上一章中笔者介绍了refresh()的<1>处是如何获取beanFactory对象,下面我们要来学习refresh()方法的<2>处是如何调用invokeBeanFactor ...
- Spring源码解析02:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
随机推荐
- spring boot 2.x 系列 —— actuator 服务监控与管理
文章目录 一.概念综述 1.1 端点 1.2 启用端点 1.3 暴露端点 1.4 健康检查信息 二.项目说明 1.1 项目结构说明 1.2 主要依赖 1.3 项目配置 1.4 查看监控状态 三.自定义 ...
- 开源joda-time使用demo
开源joda-time 1.maven中引入 <dependency> <groupId>joda-time</groupId> <artifactId> ...
- idea上MyBatis第一个例子
接着上面创建的maven项目来. 1.java目录下创建cn.happy.entity包 2.idea下创建数据库连接 配置连接参数 3.把数据库表变成实体类 导入成功,改一下包名就可以用了 4.新建 ...
- 模拟实现 Tomcat 的核心模块:NIO,HTTP,容器和集群
如果你想看 Tomcat 源码但又无从入手,不妨从这个项目开始,代码量不多,但包含了 Tomcat 的核心处理流程,并且源码中有相当丰富的注释.相信通过此项目你能了解: NIO 基本编程.HTTP 协 ...
- MxNet 模型转Tensorflow pb模型
用mmdnn实现模型转换 参考链接:https://www.twblogs.net/a/5ca4cadbbd9eee5b1a0713af 安装mmdnn pip install mmdnn 准备好mx ...
- POJ 2175:Evacuation Plan(费用流消圈算法)***
http://poj.org/problem?id=2175 题意:有n个楼,m个防空洞,每个楼有一个坐标和一个人数B,每个防空洞有一个坐标和容纳量C,从楼到防空洞需要的时间是其曼哈顿距离+1,现在给 ...
- Java线程池原理浅析
什么是线程池? 为了避免频繁重复的创建和销毁线程,我们可以让这些线程进行复用,在线程池中,总会有活跃的线程在占用,但是线程池中也会存在没有占用的线程,这些线程处于空闲状态,当有任务的时候会从池子里面拿 ...
- flask请求上下文 (转)
本篇阅读目录 一.flask中的CBV 二.werkzeug + 上下文初步解读 三.偏函数和线程安全 回到顶部 一.flask中的CBV 对比django中的CBV,我们来看一下flask中的CBV ...
- scrapy基础知识之 CrawlSpiders爬取lagou招聘保存在mysql(分布式):
items.py import scrapy class LagouItem(scrapy.Item): # define the fields for your item here like: # ...
- jekyll搭建个人博客1
目录 配置环境 使用模板 配置环境 简介 jekyll是一个简单的免费的,生成静态网页的工具,不需要数据库支持.但是可以配合第三方服务,例如Disqus.最关键的是jekyll可以免费部署在Githu ...