IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> # SpringBoot 中设计模式的使用 -> 正文阅读

[Java知识库]# SpringBoot 中设计模式的使用

SpringBoot 中设计模式的使用

友情链接:设计模式的使用:https://blog.csdn.net/qq_37248504/article/details/122991309

简单工厂

  • 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
  • SpringBoot中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。

BeanFactory 类图

请添加图片描述

工厂方法

  • 使用示例: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源码分析

  • FactoryBeangetBean方法再获取容器中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 AOPAdvisorAdapter 类有 4 个实现类,即 SimpleBeforeAdviceAdapterMethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter
    请添加图片描述
  • 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下默认的事件
    请添加图片描述
  • ContextStartedEventApplicationContext 启动后触发的事件;
  • ContextStoppedEventApplicationContext 停止后触发的事件;
  • ContextRefreshedEventApplicationContext 初始化或刷新完成后触发的事件;
  • ContextClosedEventApplicationContext 关闭后触发的事件。

事件监听者角色

  • ApplicationListener 充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()方法来处理ApplicationEventApplicationListener接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 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()ProxyFactoryBeangetObject 初始化通知链,然后根据通知生成实例对象
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 接口

SpringResource 接口提供了如下实现类:

  • UrlResource:访问网络资源的实现类。
  • ClassPathResource:访问类加载路径里资源的实现类
  • FileSystemResource:访问文件系统里资源的实现类。
  • ServletContextResource:访问相对于 ServletContext 路径里的资源的实现类
  • InputStreamResource:访问输入流资源的实现类。
  • ByteArrayResource:访问字节数组资源的实现类。

提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring 将会提供不同的 Resource 实现类,不同的实现类负责不同的资源访问逻辑。
请添加图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:29:52  更:2022-04-07 22:30:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:48:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码