前言
众所周知,Spring框架是一个强大而灵活的开发框架。这不,上次的面试刚问到这些,没防住!!!因此下来总结一下。这篇文章主要介绍Spring中使用到的设计模式,自己做个面试复盘,同时希望能帮助到其他小伙伴儿们。
工厂模式
相信大家面试题都背过,Spring通过工厂模式来创建和管理Bean的实例。工厂模式主要定义了一个用于创建对象的接口,让子类决定实例化哪一个类。在Spring中,BeanFactory
和ApplicationContext
接口是实现工厂模式的关键。
那么什么是BeanFactory
和ApplicationContext
呢???👇👇👇
BeanFactory
是Spring中最底层的容器接口,它提供了基础的依赖注入功能。ApplicationContext
扩展了BeanFactory
,并添加了更多高级功能,比如国际化、事件传播、资源加载等(这个也是面试重点!!!)。
我们以ApplicationContext
为例,它提供了getBean(String name)
方法来获取Bean实例。当调用这个方法的时候,ApplicationContext
会根据配置信息创建或获取Bean实例。
ApplicationContext context = new ClassPathXmlApplicationContext("springDemo.xml");
MyBean myBean = context.getBean("myBean", MyBean.class);
AbstractApplicationContext
的getBean
方法通过调用getBeanFactory().getBean()
来实际获取Bean实例。而BeanFactory
的实现类(比如DefaultListableBeanFactory
)负责根据Bean的定义和依赖关系来创建和管理Bean实例。
单例模式
Spring中的Bean默认都是单例的,因此在整个Spring IoC容器中,每个Bean只会有一个实例。这是通过Bean的scope
属性来进行控制的,当scope
为singleton
时,就表示使用单例模式。
翻阅了Spring的源码发现:👇👇👇
Spring通过DefaultSingletonBeanRegistry
类中的singletonObjects
(类型为ConcurrentHashMap
)来管理单例Bean的实例。当请求一个Bean时,Spring会首先检查这个Map中是否已存在该Bean的实例,如果存在则直接返回,否则创建新的实例并添加到Map中。
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 创建新的Bean实例
singletonObject = singletonFactory.getObject();
// 添加到单例注册表中
this.singletonObjects.put(beanName, singletonObject);
}
return singletonObject;
}
}
代理模式
这道题相信大家都会,面试经常被问到哈哈。Spring的AOP功能中使用了代理模式。AOP通过在目标方法执行前后添加额外的行为(比如日志、事务管理这些),而这些额外的行为是通过代理对象来实现的。Spring提供了两种代理方式:JDK动态代理和CGLIB代理。
Spring的AOP实现主要在DefaultAopProxyFactory
类中。这个类负责根据配置决定使用哪种代理方式,并创建代理对象。
if (isProxyTargetClass()) {
// 使用CGLIB代理
return createCglibProxy(beanClassLoader, beanFactory, beanClass, beanName, targetSource, interceptedMethods, proxyTargetClass);
} else {
// 使用JDK动态代理
return createJdkDynamicProxy(beanClassLoader, beanFactory, beanClass, interfaces, interceptedMethods, proxyTargetClass);
}
在createJdkDynamicProxy
这个方法中,Spring通过Proxy.newProxyInstance
方法创建一个实现了目标对象接口的代理对象,并将所有调用转发到目标对象,同时还可以在调用前后插入额外的行为。
模板方法模式
谈论到模板方法模式,相信大家都较为熟悉。比如在前面提过的AQS中也有模板方法模式的影子。
在Spring的JdbcTemplate
、HibernateTemplate
这些类中,都使用了模板方法模式。这些类定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。
以JdbcTemplate
为例,它定义了如query
、update
等方法,这些方法包含了数据库操作的通用流程(打开连接、执行SQL、处理结果集、关闭连接等),而具体的SQL语句和参数则由调用者提供。
观察者模式
Spring的事件驱动模型使用了观察者模式。当某个事件发生时,所有注册为该事件监听器的对象都会收到通知,并且根据需要作出响应。
Spring的ApplicationEvent和ApplicationListener接口是实现观察者模式的关键。ApplicationEvent是事件对象,包含了事件的信息;ApplicationListener是监听器接口,定义了处理事件的方法。
public class CustomEvent extends ApplicationEvent {
private final String message;
public CustomEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
// 实现监听器
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
// 处理事件
System.out.println("Received custom event - " + event.getMessage());
}
}
在Spring的AbstractApplicationContext中,通过ApplicationEventMulticaster来管理事件的发布和监听。当事件被发布时,ApplicationEventMulticaster会通知所有注册的监听器。
策略模式
策略模式在Spring中主要用于定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换。相信大家看过Spring中bean的生命周期这道面试题。Spring的BeanFactoryPostProcessor
和BeanPostProcessor
这些接口可以被视为策略模式的应用,因为它们允许开发者在Bean的创建和初始化过程中插入自定义的逻辑。
BeanFactoryPostProcessor允许在BeanFactory标准初始化之后,修改BeanFactory的内容。这个时候我们可以实现这个接口来定义自己的策略,然后在Spring的配置文件中注册这个Bean。
Spring还有一些其他的设计模式,看到这里面试以及能防得住了,后续再介绍其他的设计模式。
本篇文章到这里就结束了,感谢各位小伙伴们的支持!