点赞的靓仔,你最帅哦!
源码已收录github 查看源码,别忘了star哦!
开题
初入博客圈,第一个编写的专题定位在设计模式,后面曾经实现了局部设计模式的内容,设计模式是框架架构设计的根底,不能说懂设计模式才会懂框架,但懂设计模式肯定能够更好的懂框架,而对设计模式深刻理解后,当工作中遇到需要或者问题的时候,甚至可能自然而然的想到用设计模式来解决。
更重要的是,咱们学习技术是为了晋升自我,找到一份好的工作。那么作为面试中的高频题目,十分有必要把握。本文通过实践 + 实际 + 源码解读的形式来具体的完结委派模式。
委派模式
委派模式并不简单,和其字面含意相似,指委派者接管工作,而后将任务分配给具体做这个工作的对象。就像做我的项目一样,老板安顿工作给项目经理,项目经理再将工作委托给具体做工作的人。
这样咋一看和代理模式十分相似,其实能够了解委托模式就是一种非凡的代理模式,他们的区别在于各自关注的点不同,代理模式通常重视代理的过程,如前置、后置、盘绕等性能的加强;而委派模式不重视过程,重视工作的执行后果,就像老板,他不关怀项目经理把这件事件安顿给谁实现,他关注的是最终的后果。
委派模式次要波及到三种角色:委派者、工作者、工作,
如上个图例,委派者即项目经理,工作者即产品、架构师、后端,工作即要做的事件。上面通过代码实现。
工作者接口
package demo.pattren.delegate;
public interface Worker {
void doJob(Job job);
}
Job定义工作类
package demo.pattren.delegate;
import lombok.Data;
@Data
public class Job {
//理论开发中的工作类必定比较复杂,属性十分多
private String jobName;
}
Worker的其中一个实现,大抵相似。其余就省略了,能够在文章结尾去我的Github拉取源码。
package demo.pattren.delegate;
/**
* 开发
*/
public class Development implements Worker {
@Override
public void doJob(Job job) {
System.out.println("开发人员向你抛出异样,我的项目延期");
System.out.println("加班加点,开发人员实现工作");
System.out.println("开发人员黑着眼圈,并实现" + job.getJobName());
}
}
测试
package demo.pattren.delegate;
import java.util.ArrayList;
import java.util.List;
/**
* 委派模式模仿测试测试
*/
public class DelegateTest {
public static void main(String[] args) {
//工作
List<Job> project = new ArrayList<>();
Job job1 = new Job();
Job job2 = new Job();
Job job3 = new Job();
job1.setJobName("原型");
job2.setJobName("架构");
job3.setJobName("开发");
project.add(job1);
project.add(job2);
project.add(job3);
ProjectManager manager = new ProjectManager();
//产品经理委派工作,对老板来说,工作都交给项目经理,并不关怀具体谁实现
project.forEach(item -> manager.dispatch(item));
}
}
深刻源码解读委派模式
通常写代码的时候,通常会在类名前面加上设计模式的名称,比方JdbcTemplate就用到了模板模式, 委派模式在JDK以及框架中利用十分多,咱们用Delegate在Idea中查问,能够查到一大堆,几十上百个不止。
咱们找一个比拟相熟的BeanDefinitionParserDelegate,查看该类在那些中央有应用。
对于该类的作用翻译如下:
Stateful delegate class used to parse XML bean definitions.
Intended for use by both the main parser and any extension
解析XML配置的委托类,即真正解析XML内容的类。
能够同时用于主解析器以及主解析器的扩大。
如果理解过Spring的容器初始化Bean的过程,那么肯定对BeanDefinitionReader不生疏,BeanDefinitionReader是用于读取Bean定义的接口,最终解析配置返回BeanFefinition对象,Debug跟踪源码,在XML定义的Bean的解析最终是交由BeanDefinitionParserDelegate实现的,类图构造如下。
XmlBeanDefinitionReader.registerBeanDefinitions
//解析XML并注册为BeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创立reader
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
//注册解析Bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
该办法外围代码是注册解析Bean,持续追踪
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
//调用do办法,
doRegisterBeanDefinitions(doc.getDocumentElement());
}
以do结尾的都是真正干活的办法,持续追踪
protected void doRegisterBeanDefinitions(Element root) {
//保留以后结点的父委派对象,因为xml是有层级和蕴含关系,所以解决这里的时候是递归进行的,
//保障能够正确解析xml到beanDefinition
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
此时申请执行到了BeanDefinitionParserDelegate,而BeanDefinitionParserDelegate还不是真正解析的类,而是将解析的工作交由解析器解决。咱们再将类图关系欠缺,整个解析解决流程如下。
至此,整个解决流程曾经清晰。简略总结。
Spring从XML解析到BeanDefinition流程如下。
XmlBeanDefinitionReader为终点,工作交由DefaultBeanDefinitionDocumentReader解决,DefaultBeanDefinitionDocumentReader通过委托类BeanDefinitionParserDelegate将解析工作委托给真正的解析器BeanDefinitionParser的实现类解决。
发表回复