自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring用到了哪些設(shè)計模式?你知道嗎?

開發(fā) 前端
我們可以看到 Spring 框架巧妙地運用了多種設(shè)計模式,不僅提高了代碼的復(fù)用性和可維護性,還增強了框架的靈活性和擴展性。

松哥的 Spring 源碼分析課程結(jié)束好久了,今天和大伙總結(jié)下 Spring 中都用到了哪些設(shè)計模式。

Spring 作為企業(yè)級應(yīng)用開發(fā)中最受歡迎的框架之一,其內(nèi)部廣泛采用了多種設(shè)計模式,使得框架不僅功能強大,而且具有很高的可擴展性和靈活性。是我們學(xué)習(xí)設(shè)計模式不可多得的優(yōu)質(zhì)材料。

一 單例模式 (Singleton Pattern)

在 Spring 框架中,單例模式被廣泛應(yīng)用于各種組件和工具類,以確保在整個應(yīng)用程序生命周期中,這些對象只有一個實例,從而節(jié)省內(nèi)存和提高性能。

松哥這里給大家舉幾個常見的 Spring 中單例的應(yīng)用。

BeanFactory

BeanFactory 是 Spring 框架中的另一個核心接口,它負責(zé)創(chuàng)建和管理 bean。BeanFactory 的實現(xiàn)類(如 DefaultListableBeanFactory)也通常以單例模式存在。

源碼示例:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    @Override
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    @Override
    public Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    singletonObject = getEarlyBeanReference(beanName, mbd, bean);
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

DefaultListableBeanFactory 本身的初始化邏輯如下:

圖片圖片

可以看到,如果存在 BeanFactory,則先銷毀,再創(chuàng)建新的 BeanFactory。

二 工廠模式 (Factory Pattern)

工廠模式提供了一種創(chuàng)建對象的接口,但讓子類決定實例化哪一個類。Spring 中的 BeanFactory 接口及其實現(xiàn)類(如 DefaultListableBeanFactory)就是工廠模式的應(yīng)用。通過這些工廠,我們可以方便地管理和創(chuàng)建bean實例。

Spring 源碼案例

public interface BeanFactory {
    Object getBean(String name) throws BeansException;
}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
}

DefaultListableBeanFactory 是 BeanFactory 的一個實現(xiàn),負責(zé)創(chuàng)建和管理 bean 的實例。

三 原型模式 (Prototype Pattern)

原型模式通過復(fù)制現(xiàn)有對象來創(chuàng)建新對象,而無需知道任何創(chuàng)建細節(jié)。在 Spring 中,我們可以通過設(shè)置 bean 的 scope 屬性為 prototype 來實現(xiàn)每次請求時都創(chuàng)建一個新的 bean 實例。

Spring 源碼案例

<bean id="exampleBean" class="com.example.ExampleBean" scope="prototype"/>

這個配置表示每次請求 exampleBean 時,都會創(chuàng)建一個新的實例。

四 模板方法模式 (Template Method Pattern)

在 Spring 框架中,模板方法模式被廣泛應(yīng)用于多個模塊,以提供靈活且可擴展的解決方案。模板方法模式的核心思想是定義一個操作中的算法骨架,而將一些步驟延遲到子類中實現(xiàn)。這樣,子類可以不改變算法結(jié)構(gòu)的情況下重新定義算法的某些特定步驟。

這里松哥和大家分享兩個經(jīng)典的模版方法模式:JdbcTemplate 和 PlatformTransactionManager。

JdbcTemplate

JdbcTemplate 是 Spring JDBC 模塊中的一個核心類,它使用模板方法模式來簡化數(shù)據(jù)庫操作。

模板方法:

  • execute:執(zhí)行 SQL 語句的基本方法。
  • query:查詢數(shù)據(jù)庫的基本方法。
  • update:執(zhí)行更新操作的基本方法。

具體實現(xiàn):

  • queryForObject:查詢單個對象。
  • queryForList:查詢列表。
  • batchUpdate:批量更新。

源碼示例:

public abstract class JdbcOperations {
    public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
        return queryForObject(sql, args, getJdbcOperations().new SingleColumnRowMapper(rowMapper));
    }

    public int update(String sql, PreparedStatementSetter pss) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL update [" + sql + "]");
        }
        Connection con = DataSourceUtils.getConnection(getDataSource());
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            pss.setValues(ps);
            int rows = ps.executeUpdate();
            if (logger.isDebugEnabled()) {
                logger.debug(rows + " rows affected");
            }
            return rows;
        } catch (Throwable ex) {
            // Handle exception
            throw translateException("PreparedStatement", sql, ex);
        } finally {
            JdbcUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }
}
PlatformTransactionManager

PlatformTransactionManager 接口定義了事務(wù)管理的基本方法,具體的事務(wù)管理實現(xiàn)類(如 DataSourceTransactionManager)則提供了具體的實現(xiàn)。

模板方法:

  • getTransaction:獲取事務(wù)。
  • commit:提交事務(wù)。
  • rollback:回滾事務(wù)。

具體實現(xiàn):

  • DataSourceTransactionManager:基于數(shù)據(jù)源的事務(wù)管理。
  • JtaTransactionManager:基于JTA的事務(wù)管理。

源碼示例:

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager {
    @Override
    protected TransactionStatus doBegin(Object transaction, TransactionDefinition definition) {
        // 獲取數(shù)據(jù)庫連接
        ConnectionHolder conHolder = (ConnectionHolder) transaction;
        Connection con = conHolder.getConnection();

        // 設(shè)置事務(wù)隔離級別
        Integer previousIsolationLevel = DataSourceUtils.storeIsolationLevelIfNotSet(con, definition.getIsolationLevel());

        // 開啟事務(wù)
        boolean newTransaction = false;
        if (!con.getAutoCommit()) {
            logger.debug("Not switching JDBC Connection [" + con + "] to manual commit because already manually committed");
        } else {
            newTransaction = true;
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            con.setAutoCommit(false);
        }

        // 返回事務(wù)狀態(tài)
        return new DataSourceTransactionObject(conHolder, previousIsolationLevel, newTransaction);
    }
}

五 適配器模式 (Adapter Pattern)

適配器模式將一個類的接口轉(zhuǎn)換成客戶希望的另一個接口。SpringMVC 中的 HandlerAdapter 接口及其多個實現(xiàn)類(如 RequestMappingHandlerAdapter)就是適配器模式的應(yīng)用,它們負責(zé)處理不同類型的控制器方法。

Spring 源碼案例

public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof HandlerMethod;
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return ((HandlerMethod) handler).invokeAndHandle(request, response);
    }
}

RequestMappingHandlerAdapter 適配了 HandlerMethod 類型的控制器方法,使其能夠處理HTTP請求。

六 裝飾者模式 (Decorator Pattern)

裝飾者模式允許動態(tài)地給一個對象添加一些額外的職責(zé)。Spring AOP 中的切面實現(xiàn)可以看作是對原有對象的一種裝飾。通過 @Around 注解定義的環(huán)繞通知可以在不改變原有業(yè)務(wù)邏輯的情況下增加額外的功能。

Spring 源碼案例

public class TransactionInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 開始事務(wù)
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

        try {
            Object result = invocation.proceed();
            transactionManager.commit(status);
            return result;
        } catch (RuntimeException ex) {
            transactionManager.rollback(status);
            throw ex;
        }
    }
}

TransactionInterceptor 是一個典型的裝飾者模式應(yīng)用,它在方法調(diào)用前后添加了事務(wù)管理的邏輯。

七 觀察者模式 (Observer Pattern)

觀察者模式定義了對象之間的一對多依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生變化時,所有依賴于它的對象都會得到通知并自動更新。Spring  中的 ApplicationEvent 和 ApplicationListener 接口共同實現(xiàn)了觀察者模式。

Spring 源碼案例

public interface ApplicationListener<E extends ApplicationEvent> {
    void onApplicationEvent(E event);
}

public class ContextRefreshedEvent extends ApplicationEvent {
    public ContextRefreshedEvent(Object source) {
        super(source);
    }
}

public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("Context refreshed!");
    }
}

MyApplicationListener 監(jiān)聽了 ContextRefreshedEvent 事件,當(dāng)上下文刷新時,會輸出一條消息。

八 代理模式 (Proxy Pattern)

代理模式為其他對象提供一個代理以控制對這個對象的訪問。Spring AOP 使用動態(tài)代理技術(shù)(JDK 動態(tài)代理或 CGLIB)來實現(xiàn)代理模式。例如,當(dāng)你在方法上添加事務(wù)管理注解 @Transactional 時,Spring 會自動創(chuàng)建一個代理對象來管理事務(wù)的開始和結(jié)束。

Spring 源碼案例

public class DefaultAopProxyFactory implements AopProxyFactory {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            return new ObjenesisCglibAopProxy(config);
        } else {
            return new JdkDynamicAopProxy(config);
        }
    }
}

DefaultAopProxyFactory 根據(jù)配置選擇使用 CGLIB 或 JDK 動態(tài)代理來創(chuàng)建代理對象。

九 組合模式 (Composite Pattern)

組合模式允許將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。在 Spring 配置中,可以將多個 bean 組合在一起形成一個復(fù)雜的結(jié)構(gòu)。

Spring 源碼案例

<beans>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

這個配置文件中,jdbcTemplate 依賴于 dataSource,形成了一個簡單的組合結(jié)構(gòu)。

十 策略模式 (Strategy Pattern)

策略模式定義了一系列算法,并將每一個算法封裝起來,使它們可以互換。Spring 中的 Resource 接口及其多個實現(xiàn)類(如 ClassPathResource, FileSystemResource)就是策略模式的應(yīng)用,可以根據(jù)需要選擇不同的資源訪問方式。

Spring 源碼案例

public interface ResourceLoader {
    Resource getResource(String location);
}

public class DefaultResourceLoader implements ResourceLoader {
    @Override
    public Resource getResource(String location) {
        if (location.startsWith("classpath:")) {
            return new ClassPathResource(location.substring("classpath:".length()));
        } else {
            return new FileSystemResource(location);
        }
    }
}

DefaultResourceLoader 根據(jù)資源路徑的前綴選擇合適的 Resource 實現(xiàn)類。

十一 小結(jié)

通過上述案例,我們可以看到 Spring 框架巧妙地運用了多種設(shè)計模式,不僅提高了代碼的復(fù)用性和可維護性,還增強了框架的靈活性和擴展性。

責(zé)任編輯:武曉燕 來源: 江南一點雨
相關(guān)推薦

2020-01-02 15:43:29

Spring設(shè)計策略

2022-09-21 09:01:27

Spring設(shè)計模式框架,

2020-03-18 09:43:37

開發(fā)技能代碼

2019-02-12 11:15:15

Spring設(shè)計模式Java

2019-11-07 11:49:14

架構(gòu)運維技術(shù)

2021-06-08 07:04:46

Dubbo設(shè)計模式

2023-07-11 08:50:34

2019-05-29 17:20:07

Spring設(shè)計模式Java

2019-12-02 10:16:46

架構(gòu)設(shè)計模式

2024-07-03 08:33:08

2021-05-31 07:58:59

Spring設(shè)計模式

2023-04-26 10:06:08

RocketMQ屬性Consumer

2022-06-30 13:41:44

SQL 語句group by

2024-02-19 08:01:59

服務(wù)微服務(wù)授權(quán)

2022-07-05 08:05:00

策略模式接口實現(xiàn)類

2023-04-28 12:37:59

Spring@Bean使用方式

2023-04-23 09:50:50

@BeanSpring

2022-08-02 06:55:35

移動設(shè)備Android

2022-12-09 19:00:02

Vite兼容性BigInt

2020-11-04 17:35:39

網(wǎng)絡(luò)安全漏洞技術(shù)
點贊
收藏

51CTO技術(shù)棧公眾號