首页 文章 精选 留言 我的

精选列表

搜索[Java],共10000篇文章
优秀的个人博客,低调大师

MyBatis 3.5.3 发布,Java 数据持久层框架

MyBatis 3.5.3 发布了,MyBatis 的前身即iBatis,是一个数据持久层(ORM)框架。它提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO)。 版本更新如下: Enhancements 在包含的 <sql /> 的 CDATA 中支持变量替换#1615 在 JDK 14+8 或更高版本上支持默认方法调用#1626 调用默认映射器方法时避免非法的反射访问警告#1636 歧义的 getter/setter 现在仅在实际访问时才抛出 ReflectionException#1201 Bugs SQL provider 引发异常时可能的无限循环#1616 如果下一个元素为 null,则无法迭代 Cursor#1653 queryCursor() 在 MySQL Connector/J 的流模式下失败#1654 发布公告:https://blog.mybatis.org/2019/10/mybatis-353-released.html

优秀的个人博客,低调大师

Java描述设计模式(14):解释器模式

本文源码:GitHub·点这里 || GitEE·点这里 一、解释器模式 1、基础概念 解释器模式是对象的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的表达式。 2、模式图解 3、核心角色 (1)、抽象表达式 Express:声明具体表达式角色需要实现的抽象接口,该接口主要提供一个interpret()方法,称做解释操作。 (2)、终结符表达式 TerminalExpress:实现抽象表达式角色接口,主要是一个interpret()方法;每个终结符都有一个具体终结表达式与之相对应。比如解析c=a+b,a和b是终结符,解析a和b的解释器就是终结符表达式。 (3)、非终结符表达式 NotTerminalExpress:每一条规则都需要一个具体的非终结符表达式用来衔接,一般是指运算符或者逻辑判断,比如c=a+b,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式。 (4)、环境容器 DataMap:一般是用来存放各个终结符所对应的具体值,比如c=a+b转换为c=1+2。这些信息需要一个存放环境。 4、源代码实现 类图结构 源码实现 public class C01_InScene { public static void main(String[] args) { DataMap dataMap = new DataMap(); TerminalExpress terminalExpress1 = new TerminalExpress("num1"); TerminalExpress terminalExpress2 = new TerminalExpress("num2"); TerminalExpress terminalExpress3 = new TerminalExpress("num3"); dataMap.putData(terminalExpress1, 1); dataMap.putData(terminalExpress2, 2); dataMap.putData(terminalExpress3, 3); // 1+2-3 = 0 System.out.println(new Minus( new Add(terminalExpress1,terminalExpress2), terminalExpress3) .interpret(dataMap)); } } // 解释器接口 interface Express { Integer interpret(DataMap dataMap) ; } // 非终结符表达式 abstract class NotTerminalExpress implements Express { Express express1,express2; public NotTerminalExpress(Express express1, Express express2){ this.express1 = express1; this.express2 = express2; } } // 终结符表达式: 1+2 终结符: 1 和 2 class TerminalExpress implements Express { public String field ; public TerminalExpress (String field){ this.field = field ; } @Override public Integer interpret(DataMap dataMap) { return dataMap.getData(this); } } // 加法表达式 class Add extends NotTerminalExpress { public Add (Express e1, Express e2) { super(e1, e2); } // 将两个表达式相减 @Override public Integer interpret(DataMap context) { return this.express1.interpret(context) + this.express2.interpret(context); } } // 减法表达式 class Minus extends NotTerminalExpress { public Minus (Express e1, Express e2) { super(e1, e2); } // 将两个表达式相减 @Override public Integer interpret(DataMap context) { return this.express1.interpret(context) - this.express2.interpret(context); } } // 数据容器 class DataMap { private Map<Express,Integer> dataMap = new HashMap<>() ; public void putData (Express key,Integer value){ dataMap.put(key,value) ; } public Integer getData (Express key){ return dataMap.get(key) ; } } 二、Spring框架应用 1、源码案例 import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; public class SpringTest { public static void main(String[] args) { SpelExpressionParser parser = new SpelExpressionParser () ; Expression expression = parser.parseExpression("(1+3-2)*3") ; Integer result = (Integer)expression.getValue() ; System.out.println("result="+result); } } 2、代码分析 (1)Expression结构 表达式接口:具有不同的实现类。 interface Expression class CompositeStringExpression implements Expression class LiteralExpression implements Expression class SpelExpression implements Expression 核心方法: Object getValue() throws EvaluationException; (2)SpelExpressionParser结构 SpelExpressionParser extends TemplateAwareExpressionParser TemplateAwareExpressionParser implements ExpressionParser interface ExpressionParser (3)ExpressionParser接口 public interface ExpressionParser { Expression parseExpression(String var1) ; Expression parseExpression(String var1, ParserContext var2) ; } (4)Expression获取 根据不同的条件获取不同的Expression对象。这里产生类的依赖关系。 源码位置:TemplateAwareExpressionParser public Expression parseExpression(String expressionString, ParserContext context) throws ParseException { if (context == null) { context = NON_TEMPLATE_PARSER_CONTEXT; } return context.isTemplate() ? this.parseTemplate(expressionString, context) : this.doParseExpression(expressionString, context); } 三、模式总结 场景 编译器、运算符表达式、正则表达式、机器人等。 优点 当有一个表达式或者语言需要解释执行,该场景下的内容可以考虑使用解释器模式,使程序具有良好的扩展性。 缺点 解释器模式会引起类膨胀,会导致程序执行和调试非常复杂,不容易理解。 四、源代码地址 GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent

优秀的个人博客,低调大师

Java描述设计模式(06):建造者模式

本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景 基于建造者模式,描述软件开发的流程。 1、代码实现 /** * 基于建造者模式描述软件开发 */ public class C01_InScene { public static void main(String[] args) { BuilderSoft builderSoft = new SoftImpl () ; ProjectManager manager = new ProjectManager(builderSoft) ; manager.createSoft(); } } /** * 手机软件产品开发 */ class MobileSoft { // 设计 private String design ; // 架构 private String frame ; // 开发 private String develop ; // 上线 private String online ; // 省略 GET SET 方法 } /** * 手机软件流程抽象类 */ abstract class BuilderSoft { // 前期工作 public abstract void earlyWork () ; // 中期工作 public abstract void midWork () ; // 后期工作 public abstract void lateWork () ; // 手机软件完成 public abstract MobileSoft builderSoft () ; } /** * 手机软件具体实现 */ class SoftImpl extends BuilderSoft { private MobileSoft mobileSoft = new MobileSoft(); @Override public void earlyWork() { System.out.println("软件前期设计..."); } @Override public void midWork() { System.out.println("软件中期架构..."); System.out.println("软件中期开发..."); } @Override public void lateWork() { System.out.println("软件后期上线..."); } @Override public MobileSoft builderSoft() { return mobileSoft ; } } /** * 项目经理:把控项目进度 */ class ProjectManager { private BuilderSoft builderSoft ; ProjectManager (BuilderSoft builderSoft){ this.builderSoft = builderSoft ; } // 统筹项目周期 public void createSoft (){ builderSoft.earlyWork(); builderSoft.midWork(); builderSoft.lateWork(); // MobileSoft mobileSoft = builderSoft.builderSoft() ; // return mobileSoft ; } } 2、代码结构图 二、建造者模式 1、基础概念 建造模式是对象的创建模式。建造模式可以将一个产品的内部属性描述与产品的生产过程分割,从而可以使一个建造过程生成具有不同的内部表象的产品对象。也就是使用一个中介对象封装一系列的对象交互,使其各个对象不需要显示的相互调用,而且可以单独的改变对象之间的交互。 2、核心角色 1)、抽象建造者(Builder)角色 给出一个抽象接口,以规范产品对象的各个组成成分的建造。模式中直接创建产品对象的是具体建造者角色。 2)、具体建造者(ConcreteBuilder)角色 完成的任务包括:1.实现抽象建造者Builder所声明的接口,给出完成创建产品实例的操作。2.在建造完成后,提供产品的实例。 3)、导演者(Director)角色 担任这个角色的类调用具体建造者角色以创建产品对象。 4)、产品(Product)角色 产品便是建造的对象。一般来说,一个系统中会有多个产品类,而且这些产品类并不一定有共同的接口,而完全可以是不相关联的。 3、模式图解 4、源码实现 /** * 建造者模式代码 */ public class C02_Builder { public static void main(String[] args) { Builder builder = new ConcreteBuilder(); Director director = new Director(builder); director.construct(); Product product = builder.builderProduct(); System.out.println(product.getAct1()); System.out.println(product.getAct2()); } } /** * 产品类 */ class Product { /*定义一些产品的操作*/ private String act1; private String act2; public String getAct1() { return act1; } public void setAct1(String act1) { this.act1 = act1; } public String getAct2() { return act2; } public void setAct2(String act2) { this.act2 = act2; } } /** * Builder 抽象建造者类 */ abstract class Builder{ public abstract void builderact1(); public abstract void builderact2(); public abstract Product builderProduct(); } /** * 具体建造者类 */ class ConcreteBuilder extends Builder{ private Product product = new Product(); @Override public void builderact1() { product.setAct1("操作一:执行..."); } @Override public void builderact2() { product.setAct2("操作二:执行..."); } @Override public Product builderProduct() { return product; } } /** * Director 导演者类 */ class Director{ /*使用建造者抽象类*/ private Builder builder; Director(Builder builder){ this.builder = builder; } /*负责调用各个建造方法*/ public void construct(){ builder.builderact1(); builder.builderact2(); } } 三、实际应用 1、JDK中应用 分析 1)、Appendable定义多个append() 抽象方法,抽象建造者。 2)、AbstractStringBuilder实现Appendable接口,已经作为了建造者,只是抽象类无法实例化。 3)、StringBuilder继承AbstractStringBuilder,即作为具体建造者,也作为指挥者。 2、Spring中应用 源码实现 // 系列方法 public BeanDefinitionBuilder setParentName(String parentName); public BeanDefinitionBuilder setFactoryMethod(String factoryMethod); public BeanDefinitionBuilder setFactoryMethodOnBean(String factoryMethod, String factoryBean); public BeanDefinitionBuilder addConstructorArgValue(@Nullable Object value); public BeanDefinitionBuilder addConstructorArgReference(String beanName); public BeanDefinitionBuilder addPropertyValue(String name, @Nullable Object value); // 构建Bean public AbstractBeanDefinition getRawBeanDefinition() { return this.beanDefinition; } public AbstractBeanDefinition getBeanDefinition() { this.beanDefinition.validate(); return this.beanDefinition; } 上面两处建造者模式的实际应用,都有点形散而神不散的感觉。 四、优缺点分析 优点:减少类之间的相互依赖,降低耦合度。 缺点:ConcreateBuilder变得臃肿庞大,逻辑复杂。 五、源代码地址 GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent

优秀的个人博客,低调大师

Java描述设计模式(04):抽象工厂模式

GitHub地址:https://github.com/cicadasmile/model-arithmetic-parent 一、抽象工厂模式 1、生活场景 汽车生产根据用户选择的汽车类型,指定不同的工厂进行生产,选择红旗轿车,就要使用中国工厂,选择奥迪轿车,就要使用德国工厂。 2、抽象工厂模式 1) 抽象工厂模式:定义了一个interface用于创建相关对象或相互依赖的对象,而无需指明具体的类;2) 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合;3) 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。4) 将工厂抽象成两层,AbstractFactory(抽象工厂) 和 具体实现的工厂子类,方便程序扩展。 3、代码UML图 4、源代码实现 /** * 抽象工厂模式 */ public class C01_AbstractFactory { public static void main(String[] args) { CarProductFactory factory = new ChinaCarFactory() ; factory.getCar("hq") ; factory = new GermanyCarFactory () ; factory.getCar("ad") ; } } // 汽车生产抽象工厂 interface CarProductFactory { CarProduct getCar (String type) ; } // 中国汽车工厂 class ChinaCarFactory implements CarProductFactory { @Override public CarProduct getCar(String type) { CarProduct product = null ; if ("hq".equals(type)){ product = new HQCar() ; product.name="红旗一号" ; product.date="1999-09-19" ; product.material(); product.origin(); } else if ("df".equals(type)){ product = new DFCar() ; product.name="东风一号" ; product.date="2019-09-19" ; product.material(); product.origin(); } return product ; } } // 德国汽车工厂 class GermanyCarFactory implements CarProductFactory { @Override public CarProduct getCar(String type) { CarProduct product = null ; if ("ad".equals(type)){ product = new ADCar() ; product.name="奥迪A8" ; product.date="2017-09-19" ; product.material(); product.origin(); } else if ("bm".equals(type)){ product = new BMCar() ; product.name="宝马X8" ; product.date="2018-09-19" ; product.material(); product.origin(); } return product ; } } // 汽车生产抽象类 abstract class CarProduct { /** * 汽车名称 */ protected String name ; /** * 生产日期 */ protected String date ; /** * 材料 */ abstract void material () ; /** * 产地 */ abstract void origin () ; } // 红旗车 class HQCar extends CarProduct { @Override void material() { System.out.println(super.name+"材料..."); } @Override void origin() { System.out.println(super.date+":"+super.name+"在中国北京生产"); } } // 东风车 class DFCar extends CarProduct { @Override void material() { System.out.println(super.name+"材料..."); } @Override void origin() { System.out.println(super.date+":"+super.name+"在中国南京生产"); } } // 奥迪车 class ADCar extends CarProduct { @Override void material() { System.out.println(super.name+"材料..."); } @Override void origin() { System.out.println(super.date+":"+super.name+"在德国柏林生产"); } } // 宝马车 class BMCar extends CarProduct { @Override void material() { System.out.println(super.name+"材料..."); } @Override void origin() { System.out.println(super.date+":"+super.name+"在德国慕尼黑生产"); } } 二、Spring框架应用 1、场景描述 Spring框架中获取配置文件中Bean的多种方式。 2、核心配置 <bean id="carBean" class="com.model.design.spring.node04.abstractFactory.CarBean"> <property name="name" value="中国红旗" /> </bean> <bean id="carBean1" class="com.model.design.spring.node04.abstractFactory.CarBean"> <property name="name" value="德国奥迪" /> </bean> 3、测试文件 这里使用了两种方式获取。 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:/spring/spring-abstract-factory.xml"}) public class SpringTest { @Resource private BeanFactory beanFactory ; @Test public void test01 (){ CarBean carBean = (CarBean)beanFactory.getBean("carBean") ; System.out.println(carBean.getName()); } @Test public void test02 (){ ApplicationContext context01 = new ClassPathXmlApplicationContext( "/spring/spring-abstract-factory.xml"); CarBean carBean = (CarBean)context01.getBean("carBean1") ; System.out.println(carBean.getName()); } } 4、结构分析 抽象工厂封装对象的创建。在Spring中,通过实现BeanFactory。可以从Spring的各种容器获取bean。根据Bean的配置,getBean方法可以返回不同类型的对象(单例作用域)或初始化新的对象(原型作用域)。在BeanFactory的实现中,我们可以区分:ClassPathXmlApplicationContext,XmlWebApplicationContext等。 三、工厂模式小结 三种工厂模式 (简单工厂模式、工厂方法模式、抽象工厂模式),工厂模式的核心用意将实例化对象的代码封装起来,放到工厂类中统一管理和维护,完成代码依赖关系的解耦。从而提高程序的可扩展性和维护性。 四、源代码地址 GitHub地址:知了一笑 https://github.com/cicadasmile/model-arithmetic-parent 码云地址:知了一笑 https://gitee.com/cicadasmile/model-arithmetic-parent

优秀的个人博客,低调大师

Java描述设计模式(02):简单工厂模式

一、生活场景简介 1、引入场景 订餐流程简单描述 1)、食品抽象类,规定食品的基础属性操作 2)、鱼类,鸡肉类食品类扩展 3)、订餐流程类,根据食品名称,加工指定类型食品 4)、模拟客户端预定操作 2、源代码实现 1)、关系图谱 2)、代码实现 /** * 简单工厂模式引入场景 */ public class C01_InScene { public static void main(String[] args) { OrderFood1 orderFood = new OrderFood1() ; orderFood.orderFood("fish") ; orderFood.orderFood("chicken") ; } } /** * 订餐流程 */ class OrderFood1 { public Food1 orderFood (String foodName){ Food1 food1 = null ; if (foodName.equals("fish")){ food1 = new FishFood1() ; food1.setName("黑鱼"); } else if (foodName.equals("chicken")){ food1 = new ChickenFood1() ; food1.setName("土鸡"); } if (food1 != null){ food1.foodMaterial(); food1.cookFood(); return food1 ; } else { return null ; } } } /** * 食物抽象类 */ abstract class Food1 { protected String name ; public abstract void foodMaterial () ; public void cookFood (){ System.out.println("食品烹饪:" + name); } public String getName() { return name; } public void setName(String name) { this.name = name; } } /** * 材料:黑鱼一条 */ class FishFood1 extends Food1 { @Override public void foodMaterial() { System.out.println("材料:黑鱼一条"); } } /** * 材料:土鸡一号 */ class ChickenFood1 extends Food1 { @Override public void foodMaterial() { System.out.println("材料:土鸡一号"); } } 3、缺点分析 1)、OCP原则:软件实体,如类、模块和函数,应当对扩展开放,但对修改关闭。2)、违反设计模式的OCP原则,新增食品类不方便扩展,代码改动较大。 二、简单工厂模式 1、基本概念 简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,是由一个工厂对象决定创建出哪个类的对象实例。 2、代码逻辑 1)、关系图谱 2)、代码实现 /** * 简单工厂模式 */ public class C02_SimpleFactory { public static void main(String[] args) { OrderFood2 orderFood2 = new OrderFood2() ; orderFood2.orderFood("chicken"); } } class OrderFood2 { private SimpleFactory simpleFactory = new SimpleFactory() ; public void orderFood (String foodName){ simpleFactory.orderFood(foodName) ; } } /** * 简单工厂类:封装食品的生产流程 */ class SimpleFactory { public Food2 orderFood (String foodName){ Food2 food2 = null ; if (foodName.equals("fish")){ food2 = new FishFood2() ; food2.setName("黑鱼"); } else if (foodName.equals("chicken")){ food2 = new ChickenFood2() ; food2.setName("土鸡"); } if (food2 != null){ food2.foodMaterial(); food2.cookFood(); return food2 ; } else { return null ; } } } abstract class Food2 { protected String name ; public abstract void foodMaterial () ; public void cookFood (){ System.out.println("食品烹饪:" + name); } public String getName() { return name; } public void setName(String name) { this.name = name; } } class FishFood2 extends Food2 { @Override public void foodMaterial() { System.out.println("材料:黑鱼一条"); } } class ChickenFood2 extends Food2 { @Override public void foodMaterial() { System.out.println("材料:土鸡一号"); } } 3、优缺点分析 1)、优点总结 该模式的核心是工厂类。这个类含有必要的逻辑判断, 可以决定在什么时候创建哪一个登录验证类的实例, 而调用者则可以免除直接创建对象的责任。简单工厂模式通过这种做法实现了对责任的分割, 当系统引入新的登录方式的时候无需修改调用者。 2)、缺点总结 这个工厂类集中了所有的创建逻辑,当有复杂的多层次等级结构时, 所有的业务逻辑都在这个工厂类中实现。什么时候它不能工作了, 整个系统都会受到影响。 三、源代码地址 GitHub地址:知了一笑 https://github.com/cicadasmile/model-arithmetic-parent 码云地址:知了一笑 https://gitee.com/cicadasmile/model-arithmetic-parent

优秀的个人博客,低调大师

Java描述设计模式(01):单例模式

一、单例模式 1、概念图解 单例设计模式定义:确保这个类只有一个实例,并且自动的实例化向系统提供这个对象。 2、样例代码 package com.model.test; public class Singleton { // 使用静态变量记录唯一实例 private static Singleton singleton = null; private Singleton (){} public static Singleton getInstance (){ if (singleton == null){ singleton = new Singleton() ; } return singleton ; } public static void main(String[] args) { Singleton singleton1 = Singleton.getInstance() ; Singleton singleton2 = Singleton.getInstance() ; /** * com.model.test.Singleton@15db9742 * com.model.test.Singleton@15db9742 */ System.out.println(singleton1); System.out.println(singleton2); } } Singleton称为单例类,构造函数使用private修饰,确保系统中只能产生一个实例,并且自动生成的。上面代码也就是所谓的懒汉式加载:只有到使用该对象的时候才来创建,意思饿了才来做饭吃。 二、线程安全问题 在上面的代码中存在一个很明显的线程安全问题,当有多条线程来请求对象实例的时候,因为对象的创建是需要时间的,假设A线程进来判断singleton == null,就会进入对象的创建过程,这时如果同时在过来几条线程,那么他们都会得到一个对象实例,这个就是所谓的线程安全问题。 1、同步控制方式 package com.model.test; public class Singleton { // 使用静态变量记录唯一实例 private static Singleton singleton = null; private Singleton (){} public static synchronized Singleton getInstance (){ if (singleton == null){ singleton = new Singleton() ; } return singleton ; } } 这样操作会影响系统性能 2、饿汉式加载 public class Singleton { // 使用静态变量记录唯一实例 private static Singleton singleton = new Singleton(); private Singleton (){} public static Singleton getInstance (){ return singleton ; } } 这里先把对象创建出来,有需要直接使用; 3、双重检查 public class Singleton { // 使用静态变量记录唯一实例 // volatile可以确保当singleton被初始化后,多线程才可以正确处理 // 被volatile修饰的变量的值,将不会被本地线程缓存 // 对该变量读写都是直接操作共享内存,确保多个线程能正确的处理该变量。 private static volatile Singleton singleton = null ; private Singleton (){} public static Singleton getInstance (){ // 如果实例不存在,则进入同步区 if (singleton == null){ // 只有第一次才会彻底执行这里面的代码 synchronized (Singleton.class) { if (singleton == null){ singleton = new Singleton() ; } } } return singleton ; } } 4、枚举方式 package com.model.design.base.node01.singleton; import org.junit.Test; /** * 类级内部类里面创建对象实例 */ public class C06_Singleton { @Test public void test01 (){ SingletonDemo INSTANCE1 = SingletonDemo.INSTANCE ; SingletonDemo INSTANCE2 = SingletonDemo.INSTANCE ; System.out.println(INSTANCE1 == INSTANCE2); INSTANCE1.info(); INSTANCE2.info(); } } enum SingletonDemo { INSTANCE ; public void info (){ System.out.println("枚举方式实现单例"); } } 三、延迟类初始化 1、基础概念 1)、类级内部类 简单点说,类级内部类指的是,有static修饰的成员式内部类。如果没有static修饰的成员式内部类被称为对象级内部类。 类级内部类相当于其外部类的static成分,它的对象与外部类对象间不存在依赖关系,因此可直接创建。而对象级内部类的实例,是绑定在外部对象实例中的。 类级内部类中,可以定义静态的方法。在静态方法中只能够引用外部类中的静态成员方法或者成员变量。 类级内部类相当于其外部类的成员,只有在第一次被使用的时候才被会装载。 2)、多线程缺省同步锁 在多线程开发中,为了解决并发问题,主要是通过使用synchronized来加互斥锁进行同步控制。但是在某些情况中,JVM已经隐含地执行了同步,这些情况下就不用自己再来进行同步控制了。这些情况包括: 1.由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时 2.访问final字段时 3.在创建线程之前创建对象时 4.线程可以看见它将要处理的对象时 2、实现方式 要想很简单地实现线程安全,可以采用静态初始化器的方式,它可以由JVM来保证线程的安全性。比如前面的饿汉式实现方式,在类装载的时候就初始化对象,不管是否需要,存在一定的空间浪费。一种可行的方式就是采用类级内部类,在这个类级内部类里面去创建对象实例。这样一来,只要不使用到这个类级内部类,那就不会创建对象实例,从而同时实现延迟加载和线程安全。 public class LazySingleton { /** * 类级内部类 */ private static class SingletonHolder { private static LazySingleton lazySingleton = new LazySingleton() ; } public static LazySingleton getInstance (){ return SingletonHolder.lazySingleton ; } public static void main(String[] args) { LazySingleton lazySingleton1 = LazySingleton.getInstance() ; LazySingleton lazySingleton2 = LazySingleton.getInstance() ; /** * com.model.test.LazySingleton@15db9742 * com.model.test.LazySingleton@15db9742 */ System.out.println(lazySingleton1+";;"+lazySingleton2); } } 四、JDK源码单例模式 Runtime单例实现源码。 1、案例演示 /** * JDK 单例模式分析 */ public class C07_Singleton { public static void main(String[] args) { Runtime runtime1 = Runtime.getRuntime() ; Runtime runtime2 = Runtime.getRuntime() ; /* * 1229416514 * 1229416514 */ System.out.println(runtime1.hashCode()); System.out.println(runtime2.hashCode()); } } 2、源代码分析 public class Runtime { private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime; } private Runtime() {} } 基于饿汉模式实现的单例模式。 五、Spring框架中应用 1、创建测试类 public class UserBean { } 2、Spring配置文件 <!-- 单例Bean --> <bean id="user" class="com.model.design.spring.node01.singleton.UserBean" /> 3、测试读取Bean对象 package com.model.design.spring.node01.singleton; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Spring框架中单例模式 */ public class S01_Singleton { @Test public void test01 (){ ApplicationContext context01 = new ClassPathXmlApplicationContext("/spring/spring-context.xml"); ApplicationContext context02 = new ClassPathXmlApplicationContext("/spring/spring-context.xml"); UserBean user01 = (UserBean)context01.getBean("user") ; UserBean user02 = (UserBean)context01.getBean("user") ; UserBean user03 = (UserBean)context02.getBean("user") ; // com.model.design.spring.node01.singleton.UserBean@364841 System.out.println(user01); // com.model.design.spring.node01.singleton.UserBean@364841 System.out.println(user02); // com.model.design.spring.node01.singleton.UserBean@c4711c System.out.println(user03); } } 结论Spring单例模式与纯粹的单例设计模式的主要区别尽管使用相同的类加载器来加载两个应用程序上下文,但是UserBean的实例是不一样的。也就是Spring框架中的单例对象是基于应用程序中。 六、单例模式总结 1、注意事项 单例模式注意事项和细节说明 1) 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。 2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new Object() 的方式。 3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象。 2、优缺点 优点: 1、单例模式只会创建一个对象实例,减少内存消耗 2、设置全局访问点,优化共享资源的访问 缺点: 1、没有接口,很难扩展 2、不利于测试 3、与单一职责原则冲突 七、源代码地址 GitHub地址:知了一笑 https://github.com/cicadasmile/model-arithmetic-parent 码云地址:知了一笑 https://gitee.com/cicadasmile/model-arithmetic-parent

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册