一、责任链模式
1、DispatcherServlet#doDispatch
getHandler 方法的处理使用到了责任链模式,handlerMappings 是之前 Spring 容器初始化好的,通过遍历 handlerMappings 查找与 request 匹配的 Handler, 这里返回 HandlerExecutionChain 对象
2、Spring AOP
JdkDynamicAopProxy#invoke()方法核心代码:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
*******
// 将切面上的通知封装成责任链
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 通过调用责任链+递归的方式执行
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
*******
}
二、监听者模式
Spring容器刷新中的AbstractApplicationContext#finishRefresh()方法。
Spring容器已经大致刷新完成,此时会调用AbstractApplicationContext#publishEvent(ApplicationEvent)方法进行上下文刷新完成事件广播,Dubbo的服务暴露就是在此时执行的!
我们知道,< dubbo:service > 标签会被解析成 ServiceBean,ServiceBean 实现了 ApplicationListener,在 Spring 容器初始化的时候会调用 onApplicationEvent 方法。ServiceBean 重写了 onApplicationEvent 方法,实现了服务暴露的功能。
ServiceBean#onApplicationEvent
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!isExported() && !isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
// 暴露服务
export();
}
}
三、模板方法模式:
1、AbstractApplicationContext#refresh()
父类AbstractApplicationContext定义了refresh的整个执行流程,而有些模板方法父类已实现,有些并没有实现,这就需要子类去实现。比如AbstractApplicationContext的onRefresh()方法是个空的模板方法,并没有具体的业务逻辑。而在springboot中其子类EmbeddedWebApplicationContext重写了该方法,springboot内置的容器(如Tomcat)正是在此方法中创建的!
先看下类的继承关系:
接下来再进入TomcatEmbeddedServletContainerFactory#getEmbeddedServletContainer()方法看下Tomcat是如何创建的。
@Override
public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory
: createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatEmbeddedServletContainer(tomcat);
}
2、JdbcTemplate
四、策略模式
先看下策略模式的UML图:
上图中的Strategy接口是策略接口类,StrategyA、StrategyB是具体的策略,而StrategyContext是策略的决策者,由它来指定使用哪个策略。
Spring的资源访问接口Resource就是策略,而它有多个具体资源访问类,如下:
那context策略决策者是谁?这个就是我们的ApplicationContext!
public static void main(String[] args) {
//1、加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring.xml");
//2、通过配置文件获取一个bean并打印
System.err.println(ctx.getBean("stu").toString());
}
上面代码是我们常用的加载Spring的配置文件的方式,ClassPathXmlApplicationContext它指定了了我们具体用哪个资源实现策略。
ClassPathXmlApplicationContext#ClassPathXmlApplicationContext()
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
// 此处指定了用ClassPathResource策略加载
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
ClassPathResource是Resource的子类