策略模式-简单实现和Spring源码中的使用分析

设计模式-总览icon-default.png?t=LBL2https://mp.csdn.net/mp_blog/creation/editor/122202507目录

一、策略模式

1、 创建一个策略抽象

2、策略的N中实现

3、为策略的调用创建一个触发容器(方法调用触发)

4、测试简单的策略模式

二、Spring中的策略模式

1、Spring MVC中 DispatcherServlet 使用策略模式


    策略模式其实之前一直想写的,并且在项目中也用过。但是最近项目上进行重构,想将一个枚举类的判断转为策略进行调用,解耦方便扩展时,发现自己本来想的觉得挺简单,但是却废了很多精力。之前一直觉得用设计模式的话,梳理清楚关系,并将一大堆的逻辑放到很多新建的类里。这是势必会创建很多的类,这样在gc方面影响还是有的。现在觉得很多时候我们可能真的需要去做一些看上去脱裤子放屁的事,并且可能真的没有想象的简单。

一、策略模式

    策略模式的网上一搜索就会出现很多的说明,并且大多数的例子基本都来自《Head First设计模式》《大话设计模式》等,并且过于文字化的介绍总是让本来简单的事情更加复杂化。所以还是直接上demo,方便理解。Head First上的策略模式例子稍微复杂一些,代码比较多就不进行展示了,可以查看:https://github.com/kevin-lihongmin/designpattern/tree/master/src/main/java/com/kevin/designpattern/headfirst/strategy

这里可以写一个最简单的策略模式,也可以理解为Java多态。demo地址为:策略模式地址

1、 创建一个策略抽象

public abstract class AbstractStrategy {

    /**
     *  抽象的策略接口
     */
    abstract void algorithm();
}

2、策略的N中实现

public class StrategyImplOne extends AbstractStrategy {
    @Override
    void algorithm() {
        System.out.println("我实现了策略(一)的方法!!!");
    }
}
public class StrategyImplTwo extends AbstractStrategy {

    @Override
    void algorithm() {
        System.out.println("我实现了策略(二)的方法!!!");
    }
}

3、为策略的调用创建一个触发容器(方法调用触发)

public class Context {

    private AbstractStrategy strategy;

    public Context(AbstractStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     *  触发策略执行
     */
    public void strategyImpl() {
        strategy.algorithm();
    }
}

4、测试简单的策略模式

public class StrategyTest {
    public static void main(String[] args) {
        // 执行策略一
        new Context(new StrategyImplOne()).strategyImpl();
        // 执行策略二
        new Context(new StrategyImplTwo()).strategyImpl();
    }
}

5、查看结果

我实现了策略(一)的方法!!!
我实现了策略(二)的方法!!!

二、Spring中的策略模式

    当我们看完上一个策略模式的demo的时候发现并没有什么用,或者我不知道自己在项目里面怎么进行使用,所以可以看看别人的框架是怎么使用的,或者说看看好的源码中是怎么使用的。

1、Spring MVC中 DispatcherServlet 使用策略模式

    DispatcherServlet在进行转发前需要进行传说中的九大件的初始化,其中去初始化时除了 initMultipartResolver(上传文件)没有获取 Properties defaultStrategies;默认策略,其他的八大件都会使用到策略模式。先看一下 defaultStrategies为 java.util.Properties类型,定义如下:

public class Properties extends Hashtable<Object, Object> {
    // ***
}

流程梳理:

1、当Web容器启动时,ServletWebServerApplicationContext 初始化会调用其refresh()方法,则会调用 DispatcherServlet的onRefresh方法(Spring Ioc的流程可以参见:Spring Ioc和Mvc时序图

2、onRefresh方法 - > initStrategies方法 -> 初始化九大件

3、初始化时则会调用getDefaultStrategy方法。如下:

4、getDefaultStrategy实现,就是去调用了Properties这个Hashtable的key对应的value值,如下:

protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
        List<T> strategies = this.getDefaultStrategies(context, strategyInterface);
        if (strategies.size() != 1) {
            throw new BeanInitializationException("DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
        } else {
            return strategies.get(0);
        }
    }
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
        String key = strategyInterface.getName();
        String value = defaultStrategies.getProperty(key);
        if (value == null) {
            return new LinkedList();
        } else {
            String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
            List<T> strategies = new ArrayList(classNames.length);
            String[] var7 = classNames;
            int var8 = classNames.length;

            for(int var9 = 0; var9 < var8; ++var9) {
                String className = var7[var9];

                try {
                    Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
                    Object strategy = this.createDefaultStrategy(context, clazz);
                    strategies.add(strategy);
                } catch (ClassNotFoundException var13) {
                    throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var13);
                } catch (LinkageError var14) {
                    throw new BeanInitializationException("Unresolvable class definition for DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var14);
                }
            }

            return strategies;
        }
    }

5、那么Properties的值在哪里添加进去的呢,DispatcherServlet 的static静态代码块中会看见,是用Spring的Resource将配置文件中的配置加载,设置到这个Map容器中的,如下:

static {
        try {
            ClassPathResource resource = new ClassPathResource("DispatcherServlet.properties", DispatcherServlet.class);
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException var1) {
            throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + var1.getMessage());
        }
    }

6、在看看 DispatcherServlet.properties 配置就明白了,就是九大件没传时的默认值,其实也可以考虑用SPI机制实现(记得之前好像是不是有版本就是用SPI实现的)。

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

总结: web容器启动,ServletWebServerApplicationContext 的refresh方法 间接调用到 DispatcherServlet的初始九大件方法, 其中八大件在没有自定义实现的情况下,调用默认的 配置。 而默认配置则是在 DispatcherServlet的静态代码块中,由Spring的ClassPathResource将配置文件DispatcherServlet.properties中的配置加载进一个 Map容器中。只待初始化九大件时,根据不同的九大件类型作为key,调用相应的实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring和Hibernate是Java开发非常常用的两个框架,下面简单介绍一下它们的源码分析。 1. Spring源码分析 Spring是一个轻量级的IoC和AOP框架,其IoC主要是通过BeanFactory和ApplicationContext来实现的。在Spring源码,可以看到很多设计模式的运用,如工厂模式、单例模式、策略模式、代理模式等等,这些设计模式的运用使得Spring的代码更加灵活和易于维护。 其BeanFactory是Spring的核心接口,它提供了IoC容器的基本实现。ApplicationContext是BeanFactory的一个子,它提供了更多的企业级特性,如AOP、事件传递等等。在Spring源码,可以看到很多关于BeanFactory和ApplicationContext的实现,特别是在Bean的生命周期、依赖注入等方面,Spring源码展示了很多实现细节。 此外,在Spring源码,还有很多关于AOP的实现,如代理模式、动态代理、CGLIB等等。这些实现使得Spring能够很好地支持AOP的实现,从而实现了很多企业级应用的需求。 总之,Spring源码分析可以让我们更好地了解Spring实现细节,并且对于我们学习和使用Spring也有很大的帮助。 2. Hibernate源码分析 Hibernate是一个Java持久化框架,它提供了对象/关系映射和查询语言等功能。在Hibernate的源码,可以看到很多关于ORM的实现,如映射文件、Session、Transaction等等。 Hibernate的核心接口是SessionFactory和Session,它们是Hibernate的核心实现。在Hibernate的源码,可以看到很多关于Session和Transaction的实现,如缓存机制、事务管理等等。此外,在Hibernate的源码,还有很多关于查询语言的实现,如HQL、Criteria等等。 总之,Hibernate的源码分析可以让我们更好地了解Hibernate的实现细节,并且对于我们学习和使用Hibernate也有很大的帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值