Spring用到了哪些设计模式

  1. 工厂设计模式:Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
  2. 代理设计模式:Spring AOP 功能的实现。AOP (Aspect-Oriented Programming 面向切面编程) 能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
  3. 单例设计模式:Spring 中的 Bean 默认都是单例的。
  4. 模板方法模式:Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
  5. 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  6. 观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用。
  7. 适配器模式:Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配

    单例模式

    单例模式(Singleton Pattern)属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

特点

  1. 单例类只能有一个实例
  2. 单例类必须自己创建自己的唯一实例
  3. 单例类必须给所有其他对象提供这一实例。比如,通过getInstance()方法。

应用场景
因此当系统中只需要一个实例对象或者系统中只允许一个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使用单例模式。

优点
单例模式的主要优点就是节约系统资源、提高了系统效率,同时也能够严格控制客户对它的访问。也许就是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,所以扩展起来有一定的困难。

懒汉式和饿汉式

区别

实例化方面(是否Lazy延迟初始化实例)

  • 饿汉式:在类加载的时候就实例化,并且创建单例对象。类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。
  • 懒汉式:默认不会实例化,外部什么时候调用什么时候new。只有当调用getInstance的时候,才回去初始化这个单例。

性能上(内存)

  • 饿汉式:在类加载的时候就初始化,不管你是否使用,它都实例化了,所以会占据空间,浪费内存。
  • 懒汉式:什么时候需要什么时候实例化,相对来说不浪费内存。

执行效率上(锁)

  • 饿汉式:没有加任何的锁,因此执行效率比较高。
  • 懒汉式:为了保证多线程安全,因此一般使用时都会加同步锁,导致效率比饿汉式差。

多线程安全

  • 饿汉式:多线程安全。基于 classloader 机制避免了多线程的同步问题。在线程还没出现之前就已经实例化了,因此饿汉式线程一定是安全的。
  • 懒汉式:多线程不安全。因为没有加锁,默认是多线程不安全的。严格意义上来说懒汉式这种实现方式并不算是单例模式,因为如果程序中刚好有多个线程同时执行 getInstance() 方法,它们获取到的 Singleton 对象可能不是同一个,比如每个线程都单独new一个实例。因为懒汉式加载是在使用时才会去new 实例的,那么你去new的时候是一个动态的过程,是放到方法中实现的。如果这个时候有多个线程访问这个实例,这个时候实例还不存在,还在new,就会进入到方法中,有多少线程就会new出多少个实例。一个方法只能return一个实例,那最终return出哪个呢?是不是会覆盖很多new的实例?

优缺点总结

  • 饿汉式:这种方式比较常用,但容易产生垃圾对象;没有加锁,执行效率会提高;类加载时就初始化,浪费内存;基于 classloder 机制避免了多线程的同步问题;不过,实例 instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化实例显然没有达到 lazy loading 的效果。
  • 懒汉式:第一次调用才初始化,避免内存浪费;不支持多线程,必须加锁 synchronized 才能保证多线程安全,但加锁会影响效率;这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作;getInstance() 的性能对应用程序不是很关键,该方法使用不太频繁。

    实现

    ```java public class SingletonEH {//饿汉式 private static SingletonEH instance = new SingletonEH(); private SingletonEH (){} public static SingletonEH getInstance() {
    1. return instance;
    } } public class SingletonLH {//懒汉式 private static SingletonLH instance; private SingletonLH (){} public static SingletonLH getInstance() {
    1. if (instance == null) {
    2. instance = new SingletonLH();
    3. }
    4. return instance;
    } } public class SingletonLHsyn {//懒汉式+线程安全 private static SingletonLHsyn instance; private SingletonLHsyn (){} public static synchronized SingletonLHsyn getInstance() {
    1. if (instance == null) {
    2. instance = new SingletonLHsyn();
    3. }
    4. return instance;
    } }

```

工厂模式

代理模式

参考