# SpringBoot 中设计模式的使用
Posted MarlonBrando1998
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# SpringBoot 中设计模式的使用相关的知识,希望对你有一定的参考价值。
SpringBoot 中设计模式的使用
友情链接:设计模式的使用:https://blog.csdn.net/qq_37248504/article/details/122991309
简单工厂
- 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
SpringBoot
中的BeanFactory
就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean
对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
BeanFactory 类图
-
实现较为简单不做举例说明
-
容器的启动过程详见:https://blog.csdn.net/qq_37248504/article/details/123509139
工厂方法
-
使用示例:
FactoryBean
接口。 -
SpringBoot
中体现就是Mybatis
mapper
中方法的实现,mapper
接口并没有具体的实现类,但是在注入的时候并不会报错,Mybatis
结合代理模式,在getObject()
中返回一个代理的Bean
示例代码
- 实现
FactoryBean
接口,重写getObject()
,这个方法返回的是一个具体的Bean
,而不是FactoryBean
- 结合代理模式,在
getObject()
中返回一个代理对象的Bean
public class EngineFactory implements FactoryBean<CarEngine>, BeanNameAware, InvocationHandler
private static final Logger logger = LoggerFactory.getLogger(EngineFactory.class);
private String name;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
if ("fire".equalsIgnoreCase(method.getName()))
logger.info(LogConst.LOG_SUCCESS_PREFIX + "here is invoke engine:" + method.getName());
if ("close".equalsIgnoreCase(method.getName()))
logger.info(LogConst.LOG_SUCCESS_PREFIX + "here is invoke engine:" + method.getName());
return null;
@Override
public void setBeanName(String name)
this.name = name;
/**
* 获取引擎 CarEngine 的代理对象
*
* @return
*/
@Override
public CarEngine getObject()
logger.info(LogConst.LOG_SUCCESS_PREFIX + "EngineFactory to build Engine01 , EngineFactory :" + name);
CarEngine carEngine = (CarEngine) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]CarEngine.class, this);
return carEngine;
@Override
public Class<?> getObjectType()
return CarEngine.class;
/**
* 是否是单例 Bean
*
* @return
*/
@Override
public boolean isSingleton()
return true;
单例模式
- 从
FactoryBean
中获取Bean
的时候使用单例模式
@Autowired
private ApplicationContext applicationContext;
Object testService = applicationContext.getBean("testServiceImpl");
单例模式获取 Bean源码分析
FactoryBean
的getBean
方法再获取容器中Bean
的时候使用了单例模式
//一级缓存:用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存:单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference)
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
// 提前曝光的单例对象的缓存中获取Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference)
//如果为空,则锁定全局变量并进行处理。
synchronized (this.singletonObjects)
// 在完整的单例锁中一致地创建早期引用
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null)
//当某些方法需要提前初始化的时候则会调用addSingleFactory 方法将对应的ObjectFactory初始化策略存储在singletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null)
// 调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
// 放在缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
return singletonObject;
流程图
适配器模式
- 适配器模式的别名为包装器(
Wrapper
)模式,它既可以作为类结构型模式,也可以作为对象结构型模式。在适配器模式定义中所提及的接口是指广义的接口,它可以表示一个方法或者方法的集合。
Aop 中的应用
Spring AOP
的AdvisorAdapter
类有 4 个实现类,即SimpleBeforeAdviceAdapter
、MethodBeforeAdviceAdapter
、AfterReturningAdviceAdapter
和ThrowsAdviceAdapter
Spring
会根据不同的AOP
配置来确定使用对应的Advice
,与策略模式不同的是,一个方法可以同时拥有多个Advice
。
模板方法
- 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
容器启动过程 refresh() 中方法
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
// 准备刷新的上下文,系统属性以及环境变量等
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
postProcessBeanFactory()
在多个类中有重写。抽象模式的体现
Jdbctemplate
- 使用
jdbcTemplate
只需写sql
,然后对执行结果进行处理,省去了建立数据库连接与连接释放资源的重复操作,其中用的是模板方法设计模式,把重复的动作封装起来,需要处理的部分开放接口,让调用者去实现。
public abstract class MyJdbcTemplate
private static final Logger logger = LoggerFactory.getLogger(MyJdbcTemplate.class);
/**
* 数据源
*/
private DataSource dataSource;
/**
* 构造方法初始化 dataSource
*
* @param dataSource 数据源
*/
public MyJdbcTemplate(DataSource dataSource)
this.dataSource = dataSource;
/**
* Jdbc Sql 查询过程
*
* @param sql sql
* @param values values
* @return List
*/
public final List<?> executeQuery(String sql, Object[] values)
try
Connection connection = this.getConnection();
PreparedStatement pre = this.createPrepareStatement(connection, sql);
ResultSet resultSet = this.executeQuery(pre, values);
List<Object> result = new ArrayList<>();
while (resultSet.next())
result.add(rowMapper(resultSet));
resultSet.close();
pre.close();
connection.close();
return result;
catch (Exception exception)
logger.error("Error occurred :", exception);
return null;
/**
* 由子类实现
*
* @param resultSet
* @return
* @throws SQLException
*/
protected abstract Object rowMapper(ResultSet resultSet) throws SQLException;
/**
* 执行查询
*
* @param preparedStatement preparedStatement
* @param values values
* @return ResultSet
* @throws SQLException
*/
private ResultSet executeQuery(PreparedStatement preparedStatement, Object[] values) throws SQLException
for (int i = 0; i < values.length; i++)
preparedStatement.setObject(i, values[i]);
return preparedStatement.executeQuery();
/**
* 对 SQL 语句进行预编译的操作
*
* @param connection connection
* @param sql sql
* @return PreparedStatement
* @throws SQLException
*/
private PreparedStatement createPrepareStatement(Connection connection, String sql) throws SQLException
return connection.prepareStatement(sql);
/**
* 获取连接
*
* @return Connection
* @throws SQLException
*/
private Connection getConnection() throws SQLException
return this.dataSource.getConnection();
观察者模式
- 观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。
Spring
事件驱动模型就是观察者模式很经典的一个应用。Spring
事件驱动模型非常有用,在很多场景都可以解耦我们的代码。
事件角色
spring-context
下默认的事件
ContextStartedEvent
:ApplicationContext
启动后触发的事件;ContextStoppedEvent
:ApplicationContext
停止后触发的事件;ContextRefreshedEvent
:ApplicationContext
初始化或刷新完成后触发的事件;ContextClosedEvent
:ApplicationContext
关闭后触发的事件。
事件监听者角色
ApplicationListener
充当了事件监听者角色,它是一个接口,里面只定义了一个onApplicationEvent()
方法来处理ApplicationEvent
。ApplicationListener
接口类源码如下,可以看出接口定义看出接口中的事件只要实现了ApplicationEvent
就可以了。所以,在Spring
中我们只要实现ApplicationListener
接口实现onApplicationEvent()
方法即可完成监听事件
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
事件发布者角色
ApplicationEventPublisher
充当了事件的发布者,它也是一个接口。
public interface ApplicationEventPublisher
default void publishEvent(ApplicationEvent event)
publishEvent((Object) event);
void publishEvent(Object event);
SpringBoot
使用事件示例见:https://blog.csdn.net/qq_37248504/article/details/115269995
代理模式
Spring Aop 的动态代理
getObject()
:ProxyFactoryBean
的getObject
初始化通知链,然后根据通知生成实例对象
public Object getObject() throws BeansException
initializeAdvisorChain();
if (isSingleton())
return getSingletonInstance();
else
if (this.targetName == null)
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
return newPrototypeInstance();
getSingletonInstance
:获取代理,然后获取实例
//创建Aop动态代理,然后获取实例
this.singletonInstance = getProxy(createAopProxy());
Mybatis Mapper 代理的实现
详细见: https://blog.csdn.net/qq_37248504/article/details/108371768
策略模式
Resource
接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。
public interface Resource extends InputStreamSource
// 返回 Resource 所指向的资源是否存在
boolean exists();
default boolean isReadable()
return exists();
// 返回 Resource 所指向的资源是否存在
default boolean isOpen()
return false;
default boolean isFile()
return false;
// 返回 Resource 所指向的资源是否存在
URL getURL() throws IOException;
URI getURI() throws IOException;
// 返回 Resource 所指向的资源是否存在
File getFile() throws IOException;
default ReadableByteChannel readableChannel() throws IOException
return Channels.newChannel(getInputStream());
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
@Nullable
String getFilename();
// 返回资源的描述信息,通常用于资源处理出错时输出该信息,通常是全限定文件名或实际 URL
String getDescription();
Resource
接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring
将会提供不同的Resource
实现类,不同的实现类负责不同的资源访问逻辑。
Spring Resource 接口
Spring
为 Resource
接口提供了如下实现类:
UrlResource
:访问网络资源的实现类。ClassPathResource
:访问类加载路径里资源的实现类FileSystemResource
:访问文件系统里资源的实现类。ServletContextResource
:访问相对于ServletContext
路径里的资源的实现类InputStreamResource
:访问输入流资源的实现类。ByteArrayResource
:访问字节数组资源的实现类。
提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring
将会提供不同的 Resource
实现类,不同的实现类负责不同的资源访问逻辑。
以上是关于# SpringBoot 中设计模式的使用的主要内容,如果未能解决你的问题,请参考以下文章