
单例模式(Singleton)是一种非常简单且容易理解的设计模式。顾名思义,单例即单一的实例,确切地讲就是指在某个系统中只存在一个实例,同时提供集中、统一的访问接口,以使系统行为保持协调一致。singleton一词在逻辑学中指“有且仅有一个元素的集合”,这非常恰当地概括了单例的概念,也就是“一个类仅有一个实例”。

package com.shu;
/**
* @description: 太阳类,世界上只有一个太阳,既然太阳系里只有一个太阳,我们就需要严格把控太阳实例化的过程。
* @author: shu
* @createDate: 2022/9/8 16:06
* @version: 1.0
*/
public class Sun {
// static关键字确保太阳的静态性
private static final Sun sun=new Sun();
// 调用该方法进行类的初始化
private static Sun getInstance(){
return sun;
}
private Sun(){
}
}
package com.shu;
/**
* @description: 太阳类,世界上只有一个太阳,既然太阳系里只有一个太阳,我们就需要严格把控太阳实例化的过程。
* @author: shu
* @createDate: 2022/9/8 16:06
* @version: 1.0
*/
public class Sun {
// static关键字确保太阳的静态性
private static Sun sun;
// 调用该方法进行类的初始化,
private static Sun getInstance(){
if(sun==null){
sun=new Sun();
}
return sun;
}
}
并发缺点
在多线程模式下是有缺陷的。试想如果是并发请求的话,判空逻辑就会同时成立,这样就会多次实例化太阳,并且对sun进行多次赋值(覆盖)操作,这违背了单例的理念。(加锁synchronized)
加锁一:将所有的等待者拒之门外,性能浪费
package com.shu;
/**
* @description: 太阳类,世界上只有一个太阳,既然太阳系里只有一个太阳,我们就需要严格把控太阳实例化的过程。
* @author: shu
* @createDate: 2022/9/8 16:06
* @version: 1.0
*/
public class Sun {
// static关键字确保太阳的静态性
private static Sun sun;
// 调用该方法进行类的初始化,
private static synchronized Sun getInstance(){
if(sun==null){
sun=new Sun();
}
return sun;
}
}
加锁二:只对关键步骤进行上锁操作,优化性能
package com.shu;
/**
* @description: 太阳类,世界上只有一个太阳,既然太阳系里只有一个太阳,我们就需要严格把控太阳实例化的过程。
* @author: shu
* @createDate: 2022/9/8 16:06
* @version: 1.0
*/
public class Sun {
// static关键字确保太阳的静态性
private volatile static Sun sun;
// 调用该方法进行类的初始化,
private static Sun getInstance(){
if(sun==null){
synchronized (Sun.class) {
sun = new Sun();
}
}
return sun;
}
}


优点
缺点
静态内部内使用
public class Singleton_00 {
public static Map<String,String> cache = new ConcurrentHashMap<String, String>();
}
CAS锁
public class Singleton_06 {
private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>();
private Singleton_06() {
}
public static final Singleton_06 getInstance() {
for (; ; ) {
Singleton_06 instance = INSTANCE.get();
if (null != instance) return instance;
INSTANCE.compareAndSet(null, new Singleton_06());
return INSTANCE.get();
}
}
public static void main(String[] args) {
System.out.println(Singleton_06.getInstance()); // org.itstack.demo.design.Singleton_06@2b193f2d
System.out.println(Singleton_06.getInstance()); // org.itstack.demo.design.Singleton_06@2b193f2d
}
}
枚举单例模式
public enum Singleton_07 {
INSTANCE;
public void test(){
System.out.println("hi~");
}
}
unsafe类
在研究多线程时会经常到这个类来,因为 CAS 就是通过 Unsafe 类来实现的。在 Unsafe 类中,Unsafe 对象也是通过单例模式获取。下面从源码中省略多余代码,提取出来单例模式部分。可以看到 Unsafe 构造方法被标记为 private,使用静态成员变量 theUnsafe 声明单例对象,并在静态代码块中进行初始化,从这里可以看出这是一个标准的饿汉式单例。
public final class Unsafe {
private static final Unsafe theUnsafe;
private Unsafe() {
}
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
static {
registerNatives();
Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});
theUnsafe = new Unsafe();
// 省略多余代码
}
Runtime类
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class Runtime are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the Runtime object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
}
Sl4fj类
public final class LoggerFactory {
private LoggerFactory() {
}
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == 0) {
Class var0 = LoggerFactory.class;
synchronized(LoggerFactory.class) {
if (INITIALIZATION_STATE == 0) {
INITIALIZATION_STATE = 1;
performInitialization();
}
}
}
// 省略多余代码
}
}

package com.shu;
/**
* @description: 敌机实体类
* @author: shu
* @createDate: 2022/9/9 14:19
* @version: 1.0
*/
public class EnemyPlane {
private int x;//敌机横坐标
private int y = 0;//敌机纵坐标
public EnemyPlane(int x) {//构造器
this.x = x;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void fly() {//让敌机飞
y++;//每调用一次,敌机飞行时纵坐标+1
}
}
package com.shu;
/**
* @description: 客服端
* @author: shu
* @createDate: 2022/9/9 14:20
* @version: 1.0
*/
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Client {
public static void main(String[] args) {
List<EnemyPlane> enemyPlanes = new ArrayList<EnemyPlane>();
for (int i = 0; i < 500; i++) {
//此处于随机纵坐标处出现敌机,采用new关键字来实例化对象
EnemyPlane ep = new EnemyPlane(new Random().nextInt(200));
enemyPlanes.add(ep);
}
}
}

package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/9 14:28
* @version: 1.0
*/
public class EnemyPlane1 implements Cloneable{
private int x;//敌机横坐标
private int y = 0;//敌机纵坐标
public EnemyPlane1(int x) {//构造器
this.x = x;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void fly() {//让敌机飞
y++;//每调用一次,敌机飞行时纵坐标+1
}
/**
* 重写克隆方法,调用该方法来实例化对象
* @return
* @throws CloneNotSupportedException
*/
@Override
protected EnemyPlane1 clone() throws CloneNotSupportedException {
return (EnemyPlane1) super.clone();
}
}
浅拷贝
/**
* @description:
* @author: shu
* @createDate: 2022/9/9 14:28
* @version: 1.0
*/
public class ShallowCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher();
teacher.setName("riemann");
teacher.setAge(28);
Student student1 = new Student();
student1.setName("edgar");
student1.setAge(20);
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone();
System.out.println(student2.getName());
System.out.println(student2.getAge());
System.out.println(student2.getTeacher().getName());
System.out.println(student2.getTeacher().getAge());
teacher.setName("jack");
System.out.println("student1的teacher为: " + student1.getTeacher().getName());
System.out.println("student2的teacher为: " + student2.getTeacher().getName());
}
}
class Teacher implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student implements Cloneable {
private String name;
private int age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object;
}
}

我们可以验证上面是结论是否正确
深拷贝
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/9 14:46
* @version: 1.0
*/
public class DeepCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher();
teacher.setName("riemann");
teacher.setAge(28);
Student student1 = new Student();
student1.setName("edgar");
student1.setAge(20);
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone();
System.out.println("-------------拷贝后-------------");
System.out.println(student2.getName());
System.out.println(student2.getAge());
System.out.println(student2.getTeacher().getName());
System.out.println(student2.getTeacher().getAge());
System.out.println("-------------修改老师的信息后-------------");
// 修改老师的信息
teacher.setName("jack");
System.out.println("student1的teacher为: " + student1.getTeacher().getName());
System.out.println("student2的teacher为: " + student2.getTeacher().getName());
}
}
class Teacher implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable {
private String name;
private int age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Object clone() throws CloneNotSupportedException {
// 浅复制时:
// Object object = super.clone();
// return object;
// 改为深复制:
Student student = (Student) super.clone();
// 本来是浅复制,现在将Teacher对象复制一份并重新set进来
student.setTeacher((Teacher) student.getTeacher().clone());
return student;
}
}


优点
缺点
/**
* Returns a shallow copy of this ArrayList instance. (The
* elements themselves are not copied.)
*
* @return a clone of this ArrayList instance
*/
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}


模拟不同的敌机进行攻击
package com.shu.common01;
/**
* @description: 敌机
* @author: shu
* @createDate: 2022/9/10 10:46
* @version: 1.0
*/
public abstract class Enemy {
private int x;
private int y;
public Enemy(int x, int y) {
this.x = x;
this.y = y;
}
/**
* 在左边绘制不同的敌机
*/
public abstract void show();
}
飞机敌机
package com.shu.common01;
/**
* @description: 飞机敌机
* @author: shu
* @createDate: 2022/9/10 10:48
* @version: 1.0
*/
public class Airplane extends Enemy{
public Airplane(int x, int y) {
super(x, y);
}
/**
* 在左边绘制不同的敌机
*/
@Override
public void show() {
System.out.println("绘制飞机敌机,进行攻击");
}
}
坦克敌机
package com.shu.common01;
/**
* @description: 坦克敌机
* @author: shu
* @createDate: 2022/9/10 10:49
* @version: 1.0
*/
public class Tank extends Enemy{
public Tank(int x, int y) {
super(x, y);
}
/**
* 在左边绘制不同的敌机
*/
@Override
public void show() {
System.out.println("绘制坦克敌机,进行攻击");
}
}
客户端
package com.shu.common01;
/**
* @description: 客服端
* @author: shu
* @createDate: 2022/9/10 10:51
* @version: 1.0
*/
import java.util.Random;
public class Client {
public static void main(String[] args) {
int screenWidth = 100;//屏幕宽度
System.out.println("游戏开始");
Random random = new Random();//准备随机数
int x = random.nextInt(screenWidth);//生成敌机横坐标随机数
Enemy airplan = new Airplane(x, 0);//实例化飞机
airplan.show();//显示飞机
x = random.nextInt(screenWidth);//坦克同上
Enemy tank = new Tank(x, 0);
tank.show();
}
}
我们可以看出代码的耦合度很高,当然我们这的实例很少,如果实例过大,代码臃肿且不易维护
我们详细一下,工厂的产出最终是产品,我们并不需要关注具体是生产流程,只关注最终的结果。
工厂
package com.shu.common01;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 11:04
* @version: 1.0
*/
import java.util.Random;
public class SimpleFactory {
private int screenWidth;
private Random random;//随机数
public SimpleFactory(int screenWidth) {
this.screenWidth = screenWidth;
this.random = new Random();
}
/**
* 根据传递不同的类型生成不同的产品
* @param type
* @return
*/
public Enemy create(String type) {
int x = random.nextInt(screenWidth);//生成敌人横坐标随机数
Enemy enemy = null;
switch (type) {
case "Airplane":
enemy = new Airplane(x, 0);//实例化飞机
break;
case "Tank":
enemy = new Tank(x, 0);//实例化坦克
break;
}
return enemy;
}
}
调用
package com.shu.common01;
/**
* @description: 客服端
* @author: shu
* @createDate: 2022/9/10 10:51
* @version: 1.0
*/
import java.util.Random;
public class Client {
public static void main(String[] args) {
SimpleFactory simpleFactory=new SimpleFactory(100);
simpleFactory.create("Airplane").show();
simpleFactory.create("Tank").show();
}
}
我们可以看到代码十分简洁,且易于维护,然而,这个简单工厂的确很“简单”,但并不涉及任何的模式设计范畴,虽然客户端中不再直接出现对产品实例化的代码,但羊毛出在羊身上,制造逻辑只是被换了个地方,挪到了简单工厂中而已,并且客户端还要告知产品种类才能产出,这无疑是另一种意义上的耦合。

优点
缺点
Calendar使用了工厂模式的简单工厂模式
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}


假设你正在开发一款家具商店模拟器。 你的代码中包括一些类, 用于表示:

我们当然是选择不同的工厂生产不同的东西,这样效率高,也方便管理
对于系列产品的每个变体, 我们都将基于 抽象工厂接口创建不同的工厂类。 每个工厂类都只能返回特定类别的产品, 例如, 现代家具工厂ModernFurnitureFactory只能创建 现代椅子ModernChair 、 现代沙发ModernSofa和 现代咖啡桌ModernCoffeeTable对象。
抽象接口
package com.shu.common02;
/**
* @description: 抽象工厂方法
* @author: shu
* @createDate: 2022/9/10 12:13
* @version: 1.0
*/
public interface FurnitureFactory {
/**
* 生成椅子
* @return
*/
Chair creatChair();
/**
* 生成办公桌
* @return
*/
CoffeeTable creatCoffeeTable();
/**
* 生成沙发
* @return
*/
Sofa creatSofa();
}
现代工厂
package com.shu.common02;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 12:25
* @version: 1.0
*/
public class ModernFurnitureFactory implements FurnitureFactory{
/**
* 生成椅子
*
* @return
*/
@Override
public Chair creatChair() {
return new Chair(180,150,"现代风格");
}
/**
* 生成办公桌
*
* @return
*/
@Override
public CoffeeTable creatCoffeeTable() {
return new CoffeeTable(180,150,"现代风格");
}
/**
* 生成沙发
*
* @return
*/
@Override
public Sofa creatSofa() {
return new Sofa(180,150,"现代风格");
}
}
维多利亚工厂
package com.shu.common02;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 12:23
* @version: 1.0
*/
public class VictorianFurnitureFactory implements FurnitureFactory{
/**
* 生成椅子
*
* @return
*/
@Override
public Chair creatChair() {
return new Chair(180,150,"维多利亚");
}
/**
* 生成办公桌
*
* @return
*/
@Override
public CoffeeTable creatCoffeeTable() {
return new CoffeeTable(180,150,"维多利亚");
}
/**
* 生成沙发
*
* @return
*/
@Override
public Sofa creatSofa() {
return new Sofa(180,150,"维多利亚");
}
}
测试
package com.shu.common02;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 12:26
* @version: 1.0
*/
public class Client02 {
public static void main(String[] args) {
// 现代风格
ModernFurnitureFactory modernFurnitureFactory = new ModernFurnitureFactory();
modernFurnitureFactory.creatChair();
modernFurnitureFactory.creatCoffeeTable();
modernFurnitureFactory.creatSofa();
// 维多利亚风格
VictorianFurnitureFactory victorianFurnitureFactory=new VictorianFurnitureFactory();
victorianFurnitureFactory.creatChair();
victorianFurnitureFactory.creatCoffeeTable();
victorianFurnitureFactory.creatSofa();
}
}


优点
缺点
总而言之,可以认为抽象工厂模式:有多个抽象产品类;一个实体工厂类可以生产多种产品类,客户可以从一个工厂获得所有想要的产品。
在 Spring 中,BeanFactory 是用于管理 Bean 的一个工厂,所有工厂都是 BeanFactory 的子类。这样我们可以通过 IOC 容器来管理访问 Bean,根据不同的策略调用 getBean() 方法,从而获得具体对象。




package com.shu;
/**
* @description: 建筑
* @author: shu
* @createDate: 2022/9/10 14:20
* @version: 1.0
*/
import java.util.ArrayList;
import java.util.List;
public class Building {
// 用List来模拟建筑物组件的组装
private List<String> buildingComponents = new ArrayList<>();
/**
* 地皮
* @param basement
*/
public void setBasement(String basement) {// 地基
this.buildingComponents.add(basement);
}
/**
* 墙
* @param wall
*/
public void setWall(String wall) {// 墙体
this.buildingComponents.add(wall);
}
/**
* 吊顶
* @param roof
*/
public void setRoof(String roof) {// 屋顶
this.buildingComponents.add(roof);
}
@Override
public String toString() {
String buildingStr = "";
for (int i = buildingComponents.size() - 1; i >= 0; i--) {
buildingStr += buildingComponents.get(i);
}
return buildingStr;
}
}
组建专业的建筑施工团队对建筑工程项目的实施至关重要,于是地产开发商决定通过招标的方式来选择施工方。招标大会上有很多建筑公司来投标,他们各有各的房屋建造资质,有的能建别墅,有的能建多层公寓,还有能力更强的能建摩天大楼,建造工艺也各有区别。但无论如何,开发商规定施工方都应该至少具备三大组件的建造能力,于是施工标准公布出来了。
package com.shu;
/**
* @description: 建造标准
* @author: shu
* @createDate: 2022/9/10 14:22
* @version: 1.0
*/
public interface Builder {
/**
* 建筑地基
*/
void buildBasement();
/**
* 建筑墙体
*/
void buildWall();
/**
* 建筑屋顶
*/
void buildRoof();
/**
* 得到最后的建筑
* @return
*/
Building getBuilding();
}
A公司
package com.shu;
/**
* @description: A施工队
* @author: shu
* @createDate: 2022/9/10 14:26
* @version: 1.0
*/
public class HouseBuilder implements Builder {
private Building house;
public HouseBuilder() {
this.house = new Building();
}
/**
* 建筑地基
*/
@Override
public void buildBasement() {
System.out.println("挖土方,部署管道、线缆,水泥加固,搭建围墙、花园。");
house.setBasement("╬╬╬╬╬╬╬╬\n");
}
/**
* 建筑墙体
*/
@Override
public void buildWall() {
System.out.println("搭建木质框架,石膏板封墙并粉饰内外墙。");
house.setWall("|田|田 田|\n");
}
/**
* 建筑屋顶
*/
@Override
public void buildRoof() {
System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");
house.setRoof("╱◥███◣\n");
}
/**
* 得到最后的建筑
*
* @return
*/
@Override
public Building getBuilding() {
return house;
}
}
B公司
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 14:30
* @version: 1.0
*/
public class ApartmentBuilder implements Builder {
private Building apartment;
public ApartmentBuilder() {
this.apartment = new Building();
}
/**
* 建筑地基
*/
@Override
public void buildBasement() {
System.out.println("深挖地基,修建地下车库,部署管道、线缆、风道。");
apartment.setBasement("╚═════════╝\n");
}
/**
* 建筑墙体
*/
@Override
public void buildWall() {
System.out.println("搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。");
for (int i = 0; i < 8; i++) {// 此处假设固定8层
apartment.setWall("║ □ □ □ □ ║\n");
}
}
/**
* 建筑屋顶
*/
@Override
public void buildRoof() {
System.out.println("封顶,部署通风井,做防水层,保温层。");
apartment.setRoof("╔═════════╗\n");
}
/**
* 得到最后的建筑
*
* @return
*/
@Override
public Building getBuilding() {
return apartment;
}
}
package com.shu;
/**
* @description: 监工
* @author: shu
* @createDate: 2022/9/10 14:32
* @version: 1.0
*/
public class Director {
public Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
/**
* 监工规定施工步骤,工程总监并不关心是哪个施工方来造房子,更不关心施工方有什么样的建造工艺,
* 但他能保证对施工工序的绝对把控,也就是说,工程总监只控制施工流程。
* @return
*/
public Building direct(){
builder.buildBasement();
builder.buildWall();
builder.buildRoof();
return builder.getBuilding();
}
}
测试
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 14:36
* @version: 1.0
*/
public class Client {
public static void main(String[] args) {
Director director = new Director(new HouseBuilder());
Building direct = director.direct();
System.out.println(direct);
System.out.println("----------------------------------------");
Director director1 = new Director(new ApartmentBuilder());
Building direct1 = director1.direct();
System.out.println(direct1);
}
}


优点
缺点
public final class StringBuilder
extends AbstractStringBuilder
implements Serializable, CharSequence
{
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
...
@Override
public String toString() {
// 创建拷贝对象, 不分享内部的字符数组
return new String(value, 0, count);
}
}
mybatis 的 SqlSessionFactoryBuilder 类 用到了建造者模式,而且在 Mybatis中SqlSessionFactory是由SqlSessionFactoryBuilder产生的
public class SqlSessionFactoryBuilder {
...
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
解析配置文件
package org.apache.ibatis.builder.xml;
...
public class XMLConfigBuilder extends BaseBuilder {
// 解析配置累
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
// 1.读取XML的标签
propertiesElement(root.evalNode("properties"));
// 2. 读取XML的标签
Properties settings = settingsAsProperties(root.evalNode("settings"));
// 3. 加载自定义的配置
loadCustomVfs(settings);
loadCustomLogImpl(settings);
// 4. 加载XML的 标签
typeAliasesElement(root.evalNode("typeAliases"));
// 5. 加载XML的 标签
pluginElement(root.evalNode("plugins"));
// 6. 加载XML的 标签
objectFactoryElement(root.evalNode("objectFactory"));
// 7. 加载XML的标签
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
// 8. 加载XML的 标签
reflectorFactoryElement(root.evalNode("reflectorFactory"));
// 9. 更新设置
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
// 10. 加载XML的 标签
environmentsElement(root.evalNode("environments"));
// 11. 加载XML的 标签
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
// 12. 加载XML的 标签
typeHandlerElement(root.evalNode("typeHandlers"));
// 13. 加载XML的 标签
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
}