Spring中都使用了哪些设计模式?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中都使用了哪些设计模式?相关的知识,希望对你有一定的参考价值。
参考技术A ● 代理模式:在AOP中有使用● 单例模式:Bean默认是单例模式
● 模板方法模式:JdbcTemplate
● 工厂模式:BeanFactory
● 观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用,比如,ContextStartedEvent就是ApplicationContext启动后触发的事件
● 适配器模式:Spring MVC中也是用到了适配器模式适配Controller
JDK中都使用了哪些常用的设计模式?先来聊一种最常用的!
我们都知道,Java中构造线程的方式有两种,第一种是继承Thread类,然后覆写run方法;第二种是实现Runnable接口,然后实现run方法。但是最终启动的时候都是通过Thread对象的start方法启动的。那么既然逻辑写在了run方法中,启动的时候为什么调用start方法呢?
一、JDK Thread类的start方法源码解析
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
通过查看源码可以看到,在start方法中调用了start0这个方法,这个方法的实现如下:
private native void start0();
该方法是native方法,表示由JDK通过JNI来调用的。但是run方法何时调用的呢?
通过查看官方文档,可以看到说明,start0的底层实现中是调用了run方法的,只不过是通过C++实现的,感兴趣的可以翻一下对应的代码。
通过上述start方法的源码,可以总结出以下几个点:
-
当线程被构造完成之后,有个状态变量会记录线程的状态,就是上述的threadStatus,初始值在类中声明的为0; -
调用start方法启动线程之后,threadStatus的值会被改变。如果再次重复调用start方法启动同一个线程时,会抛出IllegalThreadStateException异常; -
thread线程启动之后,会被加入到一个线程组ThreadGroup中; -
线程如果启动失败了,线程组会对线程做失败处理,将其从线程组中移除; -
如果一个线程生命周期结束了,再次调用start方法试图启动线程的时候,会提示IllegalThreadStateException异常,也就是处于TERMINATED状态的线程没办法重新回到RUNNABLE或者RUNNING状态;
示例验证1: 验证线程是否可以启动多次
Thread thread = new Thread(){
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
thread.start();
运行上述代码,会出现以下异常信息:
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:705)
at com.wb.spring.test.TestThread.main(TestThread.java:40)
示例验证2: 线程生命周期结束,再次调用start方法启动
Thread thread = new Thread(){
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(1);
System.out.println("线程运行完毕!");
} catch (Exception e) {
e.printStackTrace();
}
}
};
// 第一次启动
thread.start();
try {
TimeUnit.MILLISECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
// 第二次启动
thread.start();
运行以上示例代码,将会得到如下的结果:
线程运行完毕!
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:705)
at com.wb.spring.test.TestThread.main(TestThread.java:48)
从结果中可以看出,线程运行完成之后,生命周期就结束了,不能再次启动。
从上述示例中可以看到,都跑出了IllegalThreadStateException异常,但是两次出现该异常的情况却不一样。第一种线程还活着,生命周期未结束,只是不允许多次重复启动;而第二次是因为线程的生命周期已经结束,试图启动已经结束的线程,就会抛出该异常。
二、Thread类中的设计模式-模板设计模式
简介: 模板设计模式指的是在继承结构中,父类中来确定算法结构,而具体的算法实现细节交给子类来完成。比如Thread类中run方法的源码如下,如果使用了Thread类的方式构造线程,其实run方法相当于一个空的实现,但是调用start方法的时候,却能够正确执行子类run方法的实现细节
@Override
public void run() {
if (target != null) {
target.run();
}
}
这种设计模式有利于父类确定程序的结构。
模板设计模式示例:
public class TemplateTest {
public final void say(String msg) {
System.out.println("000000");
sayHello(msg);
System.out.println("000000");
}
protected void sayHello(String msg) {
}
public static void main(String[] args) {
TemplateTest test1 = new TemplateTest() {
@Override
protected void sayHello(String msg) {
System.out.println("***" + msg + "***");
}
};
test1.say("wb");
TemplateTest test2 = new TemplateTest() {
@Override
protected void sayHello(String msg) {
System.out.println("&&&" + msg + "&&&");
}
};
test2.say("bw");
}
}
输入结果如下:
000000
***wb***
000000
000000
&&&bw&&&
000000
可以看到,需要输入什么符号,可以自由地由子类来控制!这就是模板设计模式带来的好处!以上就是Thread类启动线程的过程及使用的设计模式!
近期精彩回顾:
MySQL系列文章
Spring系列文章
Java系列文章
ElasticSearch系列文章
常驻内容:
源码搭建:
关注菜鸟封神记,定期分享技术干货!
有收获给个赞和在看呗,感谢↓↓↓
以上是关于Spring中都使用了哪些设计模式?的主要内容,如果未能解决你的问题,请参考以下文章