输入“/”快速插入内容

Spring中的设计模式

控制反转(IoC)和依赖注入(DI)
IoC是Spring中的一个非常重要的概念,它不是什么技术,而是一种解耦的设计思想,IoC的主要目的是借助于第三方实现具有依赖关系的对象之间的解耦(IOC容器管理对象),从而降低代码之间的耦合度
IoC是一个原则,不是一个模式,以下模式(但不限于)实现了IoC原则
Spring IoC容器就像是一个工厂一样,当我们需要创建一个对象时,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。IoC容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁
在实际项目中,一个Service类如果有几百甚至上千个类作为它的底层,我们需要实例化这个Service,你可以每次都要搞清这个Service所有底层类的构造函数,这可能会把人逼疯。若利用IoC的话,只需要配置好,在需要的地方引用就行,大大增加了项目的可维护性且降低了开发难度
控制反转怎么理解呢? 举个例子:"对象 a 依赖了对象 b,当对象 a 需要使用 对象 b 的时候必须自己去创建。但是当系统引入了 IOC 容器后, 对象 a 和对象 b 之间就失去了直接的联系。这个时候,当对象 a 需要使用 对象 b 的时候, 我们可以指定 IOC 容器去创建一个对象 b 注入到对象 a 中"。 对象 a 获得依赖对象 b 的过程,由主动行为变为了被动行为,控制权反转,这就是控制反转名字的由来。
DI(Dependency Inject,依赖注入)是实现控制反转的一种设计模式,依赖注入就是将实例变量传入到一个对象中去
工厂设计模式
Spring使用工厂模式可以通过 BeanFactoryApplicationContext 创建bean对象
两者对比:
BeanFactory:延迟注入(使用到某个bean时才会注入),相比于ApplicationContext来说会占用更少的内存,程序启动速度更快
ApplicationContext:容器启动时,不管是否用到,一次性创建所有bean,BeanFactory仅提供了最基本的依赖注入支持,ApplicationContext扩展了BeanFactory,除了有BeanFactory的功能外还有额外更多功能,所以一般开发任意使用ApplicationContext会更多
ApplicationContext的三个实现类
1.
ClassPathXmlApplication:把上下文文件当成类路径资源
2.
FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
3.
XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息
Example:
代码块
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
"C:/work/IOC Containers/springframework.applicationcontext/src/main/resources/bean-factory-config.xml");
HelloApplicationContext obj = (HelloApplicationContext) context.getBean("helloApplicationContext");
obj.getMsg();
}
}
单例设计模式
单例模式的介绍
在系统中,有一些对象只需要一个,比如说:线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象,事实上,这类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,如:程序的行为异常、资源使用量、或者不一致性的结果
使用单例模式的好处:
对于频繁使用的对象,省略创建对象所花费的时间,对于重量级对象,是非常可观的一笔系统开销
new操作次数减少,对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间
Spring中bean的默认作用域是singleton(单例)的,除了singleton作用域,Spring中bean还有下面几种作业域:
prototype:每次获取都会创建一个新的bean实例。连续两次getBean(),得到是不同的Bean实例
request(仅Web应用可用):每一次HTTP请求都会产生一个新的bean(请求bean),该bean仅在当前HTTP request内有效
session(仅Web应用可用):每一次来自新session的HTTP请求都会产生一个新的bean(会话bean),该bean仅在当前HTTP session内有效
application/global-session(仅Web应用可用):每个Web应用在启动时创建一个Bean(应用Bean),该bean仅在当前应用启动时有效
websocket(仅Web应用可用):每一次WebSocket会话产生一个新的bean
Spring通过ConcurrentHashMap实现单例注册表的特殊方式实现单例模式
Spring实现单例的核心代码
代码块
// 通过 ConcurrentHashMap(线程安全) 实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//...省略了很多代码
try {
singletonObject = singletonFactory.getObject();
}
//...省略了很多代码
// 如果实例对象在不存在,我们注册到单例注册表中。
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
//将对象添加到单例注册表
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
}
}