首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
CGLIB AopProxy实现 - CglibAopProxy
AopProxyFactory配置管理器 - AdvisedSupport
Advisor链工厂接口与实现 - AdvisorChainFactory
目标对象来源接口与实现 - TargetSource
代理对象创建基础类 - ProxyCreatorSupport
AdvisedSupport事件监听器 - AdvisedSupportListener
ProxyCreatorSupport标准实现 - ProxyFactory
ProxyCreatorSupport IoC容器实现 - ProxyFactoryBean
ProxyCreatorSupport AspectJ实现 - AspectJProxyFactory
IoC容器自动代理抽象 - AbstractAutoProxyCreator
IoC容器自动代理标准实现
IoC容器自动代理 AspectJ 实现 - AspectJAwareAdvisorAutoProxyCreator
AOP Infrastructure Bean接口 - AopInfrastructureBean
AOP上下文辅助类 - AopContext
代理工厂工具类 - AopProxyUtils
AOP工具类 - AopUtils
AspectJ Enable模块驱动实现 - @EnableAspectJAutoProxy
AspectJ XML配置驱动实现 -
AOP配置Schema-based 实现 -
Aspect Schema-based实现 -
Pointcut Schema-based实现 -
Around Advice Schema-based实现 -
Before Advice Schema-based实现 -
After Advice Schema-based实现 -
After Returning Advice Schema-based实现 -
After Throwing Advice Schema-based实现 -
Adviser Schema-based实现 -
Introduction Schema-based实现 -
作用域代理Schema-based实现 -
抽象工厂模式(Abstract factory)实现
构建器模式(Builder)实现
工厂方法模式(Factory method)实现
原型模式(Prototype)实现
单例模式(Singleton)实现
适配器模式(Adapter)实现
组合模式(Composite)实现
装饰器模式(Decorator)实现
享元模式(Flyweight)实现
代理模式(Proxy)实现
模板方法模式(Template Method)实现
责任链模式(Chain of Responsibility)实现
观察者模式(Observer)实现
策略模式(Strategy)实现
命令模式(Command)实现
状态模式(State)实现
Spring AOP在 Spring 事件(Events)
Spring AOP在Spring 事务(Transactions)理论基础
Spring AOP在Spring 事务(Transactions)源码分析
Spring AOP在Spring 缓存(Caching)
Spring AOP在Spring本地调度(Scheduling)
当前位置:
首页>>
技术小册>>
Spring AOP 编程思想(下)
小册名称:Spring AOP 编程思想(下)
### 单例模式(Singleton)实现 在软件工程中,单例模式是一种常用的设计模式,它确保一个类仅有一个实例,并提供一个全局访问点来获取这个唯一的实例。这种模式在需要控制资源访问、实现配置信息的读取、管理数据库连接池等场景中尤为有用。在Spring AOP的上下文中,虽然AOP本身更多关注于横切关注点(如日志、事务管理等),但了解如何在Spring框架中实现单例模式对于理解和优化Spring应用同样重要。本章将深入探讨单例模式的概念、实现方式,并特别关注在Spring框架中的实践。 #### 一、单例模式的概念 单例模式的核心在于确保一个类只有一个实例,并提供一个全局访问点。这个全局访问点通常是一个静态方法,它负责创建类的唯一实例(如果尚未创建)并在后续请求时返回这个实例。单例模式的关键在于控制实例的创建和访问,以避免多个实例导致的资源浪费或数据不一致问题。 #### 二、单例模式的实现方式 单例模式有多种实现方式,每种方式都有其特点和适用场景。以下是几种常见的实现方式: ##### 1. 懒汉式(线程不安全) 懒汉式单例模式在类内部声明了一个静态的实例对象,并在第一次使用时创建。这种实现方式简单,但在多线程环境下存在线程安全问题。 ```java public class SingletonLazyUnsafe { private static SingletonLazyUnsafe instance; private SingletonLazyUnsafe() {} public static SingletonLazyUnsafe getInstance() { if (instance == null) { instance = new SingletonLazyUnsafe(); } return instance; } } ``` ##### 2. 懒汉式(线程安全) 为了解决懒汉式在多线程环境下的线程安全问题,可以通过在`getInstance`方法上添加`synchronized`关键字来实现。但这样做会降低效率,因为每次调用`getInstance`时都会进行线程锁定。 ```java public class SingletonLazySafe { private static SingletonLazySafe instance; private SingletonLazySafe() {} public static synchronized SingletonLazySafe getInstance() { if (instance == null) { instance = new SingletonLazySafe(); } return instance; } } ``` ##### 3. 双重检查锁定(Double-Checked Locking) 双重检查锁定是一种优化技术,它在第一次检查实例是否为null时进行非同步操作,仅当实例确实为null时才进行同步操作,从而降低了同步的开销。 ```java public class SingletonDoubleChecked { // 使用volatile关键字防止指令重排序 private static volatile SingletonDoubleChecked instance; private SingletonDoubleChecked() {} public static SingletonDoubleChecked getInstance() { if (instance == null) { synchronized (SingletonDoubleChecked.class) { if (instance == null) { instance = new SingletonDoubleChecked(); } } } return instance; } } ``` ##### 4. 饿汉式 饿汉式单例模式在类加载时就完成了实例的初始化,因此它本身就是线程安全的。这种方式避免了多线程同步问题,但实例的创建是提前的,可能会造成资源的浪费。 ```java public class SingletonEager { // 在类加载时就完成了实例化 private static final SingletonEager instance = new SingletonEager(); private SingletonEager() {} public static SingletonEager getInstance() { return instance; } } ``` ##### 5. 静态内部类 静态内部类单例模式利用了类加载机制来确保实例的唯一性,同时延迟了实例的创建,达到了懒加载的效果,且无需额外的同步代码。 ```java public class SingletonStaticInner { private SingletonStaticInner() {} private static class SingletonHolder { private static final SingletonStaticInner INSTANCE = new SingletonStaticInner(); } public static final SingletonStaticInner getInstance() { return SingletonHolder.INSTANCE; } } ``` ##### 6. 枚举(推荐) 枚举方式是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或反射攻击时也能保持单例的唯一性。 ```java public enum SingletonEnum { INSTANCE; public void someMethod() { // 方法内容 } } ``` #### 三、Spring框架中的单例模式 在Spring框架中,默认情况下,Spring容器中的Bean都是单例的(Singleton Scope)。这意味着,无论一个Bean被注入到多少个Bean中,它们都将共享同一个实例。Spring通过IoC容器来管理Bean的生命周期和依赖关系,确保了单例模式的实现。 ##### 1. Spring中的单例作用域 在Spring中,可以通过`@Scope`注解来指定Bean的作用域。对于单例模式,可以直接省略`@Scope`注解,因为默认就是单例的。如果需要显式声明,可以这样做: ```java @Component @Scope("singleton") public class MySingletonBean { // 类的定义 } ``` 但实际上,上面的`@Scope("singleton")`是多余的,因为`singleton`是默认值。 ##### 2. Spring单例的实现机制 Spring的单例实现并非传统意义上的单例模式。在Spring容器中,每个单例Bean都只会有一个实例,但这并不意味着在整个JVM中只有一个实例。实际上,Spring的单例是基于容器的,每个Spring容器(ApplicationContext)都有自己的单例Bean缓存。如果创建了多个Spring容器,那么同一个类在不同的容器中将会有不同的实例。 此外,Spring的单例Bean并非在容器启动时立即创建,而是采用懒加载的方式,即只有在第一次被请求时才会创建实例。这种机制既节约了资源,又提高了应用的启动速度。 ##### 3. Spring单例与线程安全 由于Spring的单例Bean是跨多个用户请求共享的,因此在设计Bean时需要特别注意线程安全问题。如果Bean的状态被多个线程修改,就可能导致数据不一致的问题。解决这个问题的常用方法包括: - **无状态Bean**:尽量设计无状态的Bean,即Bean的状态不依赖于特定的请求或会话。 - **使用线程局部变量**:对于需要保持状态的Bean,可以使用`ThreadLocal`等机制来隔离线程间的数据。 - **同步方法**:在需要同步访问的Bean方法上添加`synchronized`关键字,但这会降低性能。 - **使用并发集合**:在Bean中使用并发集合来管理数据,如`ConcurrentHashMap`等。 #### 四、总结 单例模式是一种重要的设计模式,它确保了类的唯一实例,并提供了一个全局访问点。在Spring框架中,单例模式是Bean的默认作用域,通过IoC容器进行管理。了解单例模式的不同实现方式及其在Spring中的应用,有助于我们更好地设计和优化Spring应用。同时,我们也需要注意到Spring单例Bean的线程安全问题,并采取相应的措施来避免潜在的风险。
上一篇:
原型模式(Prototype)实现
下一篇:
适配器模式(Adapter)实现
该分类下的相关小册推荐:
手把手带你学习SpringBoot-零基础到实战
Java语言基础9-常用API和常见算法
Spring Cloud微服务项目实战
Java语言基础6-面向对象高级
Java必知必会-Maven高级
Mybatis合辑2-Mybatis映射文件
Java并发编程实战
Java语言基础13-类的加载和反射
JAVA 函数式编程入门与实践
Java必知必会-Maven初级
SpringBoot合辑-高级篇
java源码学习笔记