SpringBoot 中设计模式的使用
友情链接:设计模式的使用:https://blog.csdn.net/qq_37248504/article/details/122991309
简单工厂
- 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
SpringBoot 中的BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean 对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
BeanFactory 类图
工厂方法
示例代码
- 实现
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;
}
@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;
}
@Override
public boolean isSingleton() {
return true;
}
}
单例模式
- 从
FactoryBean 中获取Bean 的时候使用单例模式
@Autowired
private ApplicationContext applicationContext;
Object testService = applicationContext.getBean("testServiceImpl");
单例模式获取 Bean源码分析
FactoryBean 的getBean 方法再获取容器中Bean 的时候使用了单例模式
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
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)) {
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) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
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;
public MyJdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
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;
}
protected abstract Object rowMapper(ResultSet 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();
}
private PreparedStatement createPrepareStatement(Connection connection, String sql) throws SQLException {
return connection.prepareStatement(sql);
}
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 {
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 :获取代理,然后获取实例
this.singletonInstance = getProxy(createAopProxy());
Mybatis Mapper 代理的实现
详细见: https://blog.csdn.net/qq_37248504/article/details/108371768
策略模式
Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。
public interface Resource extends InputStreamSource {
boolean exists();
default boolean isReadable() {
return exists();
}
default boolean isOpen() {
return false;
}
default boolean isFile() {
return false;
}
URL getURL() throws IOException;
URI getURI() throws IOException;
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();
String getDescription();
}
Resource 接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring 将会提供不同的 Resource 实现类,不同的实现类负责不同的资源访问逻辑。
Spring Resource 接口
Spring 为 Resource 接口提供了如下实现类:
UrlResource :访问网络资源的实现类。ClassPathResource :访问类加载路径里资源的实现类FileSystemResource :访问文件系统里资源的实现类。ServletContextResource :访问相对于 ServletContext 路径里的资源的实现类InputStreamResource :访问输入流资源的实现类。ByteArrayResource :访问字节数组资源的实现类。
提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring 将会提供不同的 Resource 实现类,不同的实现类负责不同的资源访问逻辑。
|