常用开源框架中设计模式使用分析(代码片段)

布衣小工 布衣小工     2022-11-14     328

关键词:

一、前言

说起来设计模式,大家应该都耳熟能详,设计模式代表了软件设计的最佳实践,是经过不断总结提炼出来的代码设计经验的分类总结,这些模式或者可以简化代码,或者可以是代码逻辑开起来清晰,或者对功能扩展很方便…。

设计模式按照使用场景可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。

  • 创建型模式(Creational Patterns)
    对对象的实例化过程进行抽象,这使得一个系统可以不用关心这些对象是如何创建,组合,呈现的,对于类创建模式来说通过使用继承改变实例化的类,对于对象创建模式来说通过使用代理来实例化所需要的对象。

  • 结构型模式(Structural Patterns)
    通过对多个类和对象进行组合得到复杂结构的类,一般使用继承继承或者成员变量引用形式来实现。

  • 行为型模式(Behavioral Patterns)
    行为模式不仅表达了对象和类,还表达了他们之间的交互,涉及到了对象和算法的分配。

下面就带大家看下开源框架框架中是如何应用这些经典设计模式的。

二、责任链设计模式(Chain of Responsibility Pattern)

2.1 介绍

责任链模式是把多个对象串联起来形成一个链状结构,让每个对象都有机会对事件发送者的请求进行处理。责任链模式是设计模式中的行为模式,设计意图是为了使事件发送者和事件接受者之间解耦。通常责任链链中的每个对象都有下一个对象的引入(例如tomcat 里面StandardPipeline用来管理valve),或者有个同一个链管理工厂里面使用数组存放了所有的对象(例如tomcat里面ApplicationFilterChain用来关系filter)。

2.2 Tomcat中Valve链

Tomcat中StandardEngine,StandardHost,StandardContext里面都有自己StandardPipeline,下面以StandardEngine里面StandardPipeline为例讲解

 

从上面类图可知道每个Valve都要继承ValveBase类,该类里面有一个Valve的引用,实际是链中下一个节点对象,Valve就是通过每个Valve里面的next串联为链的。

 

每个valve的invoke方法里面调用next.invoke激活链中下一个节点,并且StandardEngine,StandardHost,StandardContext都有一个basic valve这个valve在链的末尾用来激活子容器的valve链。

2.3 Tomcat中Filter链

Tomcat中Filter链是使用ApplicationFilterChain来管理的,具体结构如下图:

可知Filter链不是像Valve一样在内部维护下个节点的引用,而是在ApplicationFilterChain中搞了个数组存放所有的Filter,并通过n统计Filter总个数,pos是当前filter的下标。

ApplicationFilterChain的doFilter代码如下:

 1 public void doFilter(ServletRequest request, ServletResponse response)
 2         throws IOException, ServletException 
 3         ...
 4         internalDoFilter(request,response);
 5         ...
 6     
 7 
 8 
 9 private void internalDoFilter(ServletRequest request, 
10                                   ServletResponse response)
11         throws IOException, ServletException 
12 
13         // Call the next filter if there is one
14         if (pos < n) 
15 
16             //获取filter链中下标为pos的filter
17             ApplicationFilterConfig filterConfig = filters[pos++];
18             Filter filter = null;
19             try 
20                 filter = filterConfig.getFilter();
21                 support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
22                                           filter, request, response);
23 
24                 if (request.isAsyncSupported() && "false".equalsIgnoreCase(
25                         filterConfig.getFilterDef().getAsyncSupported())) 
26                     request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
27                             Boolean.FALSE);
28                 
29 
30                 ...
31 
32                 //调用自定义filter的dofilter方法
33                 filter.doFilter(request, response, this);
34 
35 
36                 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
37                                           filter, request, response);
38              
39             ....
40 
41     
42    .....
43 

 

注:这两种方式的区别是啥,就是说那些场景下使用2.2,什么情况下使用2.3这个目前还没有搞清楚有
知道的麻烦在本帖留言帮我解惑下^^

2.4 使用场景

  • 当一个请求需要
    根据请求参数的不同由不同对象来处理时候。

  • 当一个请求需要固定对象顺序处理,并且可扩展性的在固定顺序里面插入新的对象进行处理时候。

三、工厂模式(Factory Pattern)

3.1 介绍

工厂模式是创建型模式,他封装了对象的创建过程,调用者使用具体的工厂方法根据参数就可以获取对应的对象。

3.2 Spring框架中BeanFactory

如图BeanFactory接口提供了getBean方法,在AbstractBeanFactory中实现了该方法,经过层层继承,实现,最后DefaultListableBeanFactory实现了BeanDefinitionRegistry接口用来保存bean定义,继承了AbstractAutowireCapableBeanFactory用来支撑autowired。

一个例子

 1 @Test
 2 public void testBeanFactoy() throws NamingException, SQLException, ParseException, IOException 
 3 
 4     //创建Bean工厂
 5     DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
 6 
 7     //给bean工厂添加bean定义,解析xml里面的bean放入bean工厂
 8     loadBeanDefinitions(bf);
 9 
10     //根据名字从bean工厂获取bean
11     Hello hello = (Hello) bf.getBean("hello");
12     hello.sayHello();
13 
14     Hello2 hello2 = (Hello2) bf.getBean("hello2");
15     hello2.sayHello();
16 
17 
18 
19 
20 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException 
21     XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
22 
23     String[] configLocations = new String[]  "beans2.xml" ;
24     if (configLocations != null) 
25         beanDefinitionReader.loadBeanDefinitions(configLocations);
26     
27 

 

3.3 使用场景

  • 不同条件下创建不同实例,用于统一管理bean

  • 不同条件下调用不同工厂方法获取不同场景下的bean

四、单例设计模式(Singleton Pattern)

4.1 介绍

单例模式是一种创建型模式,单例模式提供一个创建对象的接口,但是多次调用该接口返回的是同一个实例的引用,目的是为了保证只有一个实例,并且提供一个访问这个实例的统一接口。

4.2 Spring中单例bean的创建

Spring中默认配置的bean的scope为singleton,也就是单例作用域。那么看看它是如何做到的。
在AbstractBeanFactory类里面的doGetBean方法:

 1 protected Object doGetBean(
 2             final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException 
 3 
 4     final String beanName = transformedBeanName(name);
 5     Object bean = null;
 6 
 7     // 解决set循环依赖
 8     Object sharedInstance = getSingleton(beanName);
 9     if (sharedInstance != null && args == null) 
10         ...
11     
12 
13     else 
14         ...
15         // 创建单件bean.
16         if (mbd.isSingleton()) 
17             sharedInstance = getSingleton(beanName, new ObjectFactory() 
18                 public Object getObject() throws BeansException 
19                     try 
20                         return createBean(beanName, mbd, args);
21                     
22                     catch (BeansException ex) 
23                     ...
24                         throw ex;
25                     
26                 
27             );
28             bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
29         
30        //创建原型bean
31         else if (mbd.isPrototype()) 
32             ...
33         
34         //创建request作用域bean
35         else 
36             ...
37         
38     
39             ...
40     return bean;
41 
42 getSingleton代码:
43 
44 public Object getSingleton(String beanName, ObjectFactory singletonFactory) 
45     Assert.notNull(beanName, "\'beanName\' must not be null");
46     synchronized (this.singletonObjects) 
47         Object singletonObject = this.singletonObjects.get(beanName);
48         if (singletonObject == null) 
49             ...
50             beforeSingletonCreation(beanName);
51             ...
52             try 
53                 singletonObject = singletonFactory.getObject();
54             
55             catch (BeanCreationException ex) 
56                 ...
57             
58             finally 
59                 if (recordSuppressedExceptions) 
60                     this.suppressedExceptions = null;
61                 
62                 afterSingletonCreation(beanName);
63             
64             addSingleton(beanName, singletonObject);
65         
66         return (singletonObject != NULL_OBJECT ? singletonObject : null);
67     
68 
69 
70 protected void addSingleton(String beanName, Object singletonObject) 
71     synchronized (this.singletonObjects) 
72         this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
73         this.singletonFactories.remove(beanName);
74         this.earlySingletonObjects.remove(beanName);
75         this.registeredSingletons.add(beanName);
76     
77 
78 
79 private final Map singletonObjects = CollectionFactory.createConcurrentMapIfPossible(16);

 

可知Spring内部四通过一个ConcurrentMap来管理单件bean的。获取bean时候会先看看singletonObjects中是否有,有则直接返回,没有则创建后放入。

看个时序图:

Spring的bean工厂管理的单例模式管理的是多个bean实例的单例,是工厂模式管理所有的bean,而每个bean的创建又使用了单例模式。

4.4 使用场景

  • 同一个jvm应用的不同模块需要使用同一个对象实例进行信息共享。

  • 需要同一个实例来生成全局统一的序列号

五、原型设计模式(Prototype Pattern)

5.1 介绍

相比单例设计模式,原型模式是每次创建一个对象,下面看下spring是如何使用原型模式的

5.2 Spring中原型bean的创建

创建原型bean需要在xml特别说明:

    
<bean id="hello" class="com.zlx.demo.Hello" scope="prototype"/>

 

 1 protected <T> T doGetBean(
 2         final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
 3         throws BeansException 
 4 
 5     final String beanName = transformedBeanName(name);
 6     Object bean;
 7 
 8     // Eagerly check singleton cache for manually registered singletons.
 9     Object sharedInstance = getSingleton(beanName);
10     if (sharedInstance != null && args == null) 
11      ...
12     
13 
14     else 
15         ...
16 
17         try 
18             ...
19 
20             // Create bean instance.
21             if (mbd.isSingleton()) 
22                 ...
23             
24             //创建原型bean
25             else if (mbd.isPrototype()) 
26                 // It\'s a prototype -> create a new instance.
27                 Object prototypeInstance = null;
28                 try 
29                     beforePrototypeCreation(beanName);
30                     prototypeInstance = createBean(beanName, mbd, args);
31                 
32                 finally 
33                     afterPrototypeCreation(beanName);
34                 
35                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
36             
37 
38             else 
39                 ...
40             
41         
42         catch (BeansException ex) 
43             cleanupAfterBeanCreationFailure(beanName);
44             throw ex;
45         
46     
47  ...
48     return (T) bean;
49 

 

createBean函数里面则是根据bean定义创建新bean,感兴趣的可以看看。

5.3 使用场景

  • 当有业务场景使用某个bean时候需要使用自己的一个拷贝的时候使用。

六、 策略模式(Strategy Pattern)

6.1 介绍

策略模式属于行为性模式,它定义一系列的算法对象,使用时候可以使它们相互替换。

6.2 Spring中bean实例化策略

首先看下类图:

从图知道:接口InstantiationStrategy是实例化策略接口类,它定义了三个实例化接口,然后SimpleInstantiationStrategy实现了该策略,它主要做一些简单的根据构造函数实例号bean的工作,然后CglibSubclassingInstantiationStrategy又继承了SimpleInstantiationStrategy新增了方法注入方式根据cglib生成代理类实例化方法。

在AbstractAutowireCapableBeanFactory中管理了该策略的一个对象,默认是CglibSubclassingInstantiationStrategy策略,运行时候可以通过setInstantiationStrategy改变实例化策略,如果你自己写个个策略的话。

6.3 Spring中Aop代理策略

首先看AopProxyFactory接口类提供了createAopProxy接口,这个是策略模式的接口方法。然后DefaultAopProxyFactory实现了该接口作为策略的实现者。然后ProxyCreatorSupport里面引用了AopProxyFactory,并且提供了get,set方法用来运行时改变策略,这里Spring只实现了DefaultAopProxyFactory这一个策略,如果需要自己也可以写个。

DefaultAopProxyFactory里面的createAopProxy的逻辑如下,可以在运行时根据参数决定用Cglib策略还是JDK动态代理策略生成代理类:

    
 1 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException 
 2 
 3 
 4         //如果XML打开了优化开关,或者设置为了代理目标类,或者目前类没有接口
 5         if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) 
 6             Class<?> targetClass = config.getTargetClass();
 7             if (targetClass == null) 
 8                 throw new AopConfigException("TargetSource cannot determine target class: " +
 9                         "Either an interface or a target is required for proxy creation.");
10             
11 
12             //如果有接口,或者通过Proxy.newProxyInstance生成的,则使用jdk动态代理
13             if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) 
14                 return new JdkDynamicAopProxy(config);
15             
16 
17             //使用cglib
18             return new ObjenesisCglibAopProxy(config);
19         
20         else 
21             //使用jdk动态代理
22             return new JdkDynamicAopProxy(config);
23         
24     

 

另外AopProxy也是一个策略接口类,具体实现的策略为JdkDynamicAopProxy,CglibAopProxy,ObjenesisCglibAopProxy

6.4 Tomcat中Digester解析server.xml

tomcat中的Digester是为了解析server.xml的,其中每个元素都有一个解析规则就是Rule ,类图如下:
DigestER一开始先指定不同的解析策略(Rule),然后在具体解析Server.xml时候根据节点不同使用不同解析策略来解析节点。

如图在解析每个节点时候会先找到该节点对应的解析策略,然后循环去调用所有解析策略的方法去处理。

6.5 使用场景

  • 运行时根据条件的不同使用不同的策略处理一个事情,与责任链不同在于,责任链是一个链条,一个事情可以被责任链里面所有节点处理,而 策略模式则是只有有一个对象来处理。

七、 门面模式(Facade Pattern)

7.1 介绍

门面模式是一种结构性模式,它通过新增一个门面类对外暴露系统提供的一部分功能,或者屏蔽了内部系统的复杂性,对外部仅仅暴露一个简单的接口,或者通过调用不同的服务对外提供统一的接口,让使用者对这些内部服务透明化。

7.2 模板引擎Velocity中门面模式使用

Velocity里面的VelocityEngine和Velocity类都是RuntimeInstance类的门面,后者提供了模板渲染的所有功能,前两者则是内部维护RuntimeInstance的实例,具体工作还是委托给RuntimeInstance来实现。
关于Veloctiy可以参考:https://www.atatech.org/articles/78435

如图 RuntimeInstance提供了Velocity引擎的所用功能,VelocityEngine内部直接引用了RuntimeInstance的一个实例,VelocityEngine对外暴露的服务都是委托RuntimeInstance实现,并且每次new一个VelocityEngine内部都会有RuntimeInstance的一个实例被创建。而Velocity类调用了单例模式类RuntimeSingleton里面的方法,RuntimeSingleton又是RuntimeInstance的一个单例模式。

7.3 使用场景

  • 当需要对外屏蔽一个系统的复杂性时候可以考虑使用门面模式对外提供简单可读性高的接口类

  • 当需要对外部暴露系统一部分权限的接口时候可以考虑使用门面模式减少系统权限。

  • 当系统需要调用不同服务汇总后在对外提供服务时候可以考虑使用门面模式对外屏蔽细节,之暴露一个接口。

九、装饰器模式(Decorator Pattern)

9.1 介绍

装饰器模式是一种结构性模式,它作用是对对象已有功能进行增强,但是不改变原有对象结构。这避免了通过继承方式进行功能扩充导致的类体系臃肿。

9.2 Spring中BeanDefinitionDecorator

先看下类图:

如图ScopedProxyBeanDefinitionDecorator实现了decorate方法用来对scope作用域为request的bean定义进行包装。
具体时序图为:

 1 class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator 
 2 
 3     private static final String PROXY_TARGET_CLASS = "proxy-target-class";
 4 
 5 
 6     @Override
 7     public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) 
 8         boolean proxyTargetClass = true;
 9         if (node instanceof Element) 
10             Element ele = (Element) node;
11             if (ele.hasAttribute(PROXY_TARGET_CLASS)) 
12                 proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS));
13             
14         
15 
16         // 创建scoped的代理类,并注册到容器
17         BeanDefinitionHolder holder =
18                 ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass);
19         String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName());
20         parserContext.getReaderContext().fireComponentRegistered(
21                 new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName));
22         return holder;
23     
24 
25 

 

关于ScopedProxyBeanDefinitionDecorator干啥用的那:


  
<bean id="lavaPvgInfo" class="com.alibaba.lava.privilege.PrivilegeInfo"
        scope="request">
        <property name="aesKey" value="666" />
        <aop:scoped-proxy />
  </bean>

 

其实就是处理<aop:scoped-proxy />
的,具体作用是包装lavaPvgInfo的bean定义为ScopedProxyFactoryBean,作用是实现request作用域bean.

9.3 commons-collections包中ListUtils

如图

ListUtils中的四个方法分别依赖list的四种装饰器类对List功能进行扩充和限制。
其中FixedSizeList类通过禁止add/remove操作保证list的大小固定,但是可以修改元素内容
其中UnmodifiableList类通过禁用add,clear,remove,set,保证list的内容不被修改
其中SynchronizedList类通过使用Lock 来保证add,set,get,remove等的同步安全
其中LazyList类则当调用get方法发现list里面不存在对象时候,自动使用factory创建对象.

9.4 使用场景

  • 在不改变原有类结构基础上,新增或者限制或者改造功能时候。

十、适配器模式(Adapter Pattern)

10.1 介绍

适配器模式属于结构性模式,它为两个不同接口之间互通提供了一种手段。

10.2 Spring中MethodInterceptor适配器

在Spring Aop框架中,MethodInterceptor接口被用来拦截指定的方法,对方法进行增强。

大家都知道在Aop中每个advistor 里面会有一个advice具体做切面动作,Spring提供了AspectJAfterReturningAdvice,AspectJMethodBeforeAdvice,AspectJAroundAdvice,AspectJAfterAdvice这几个advice,在XML 配置aop时候会指定<aop:after-returning/>,<aop:before/>,<aop:around/>,<aop:after/>,其实内部就是创建上面对应的这些advice。

从图知道AspectJAfterReturningAdvice和AspectJMethodBeforeAdvice没有实现MethodInterceptor接口,其他两者则实现了该接口。而Spring Aop的方法拦截器却必须是实现了MethodInterceptor的,所以Spring提供了对应的适配器来适配这个问题,分别是MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter和ThrowsAdviceAdapter。

看下DefaultAdvisorAdapterRegistry的 getInterceptors方法:

 1 public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException 
 2     List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
 3 
 4     //从advistor中获取advice
 5     Advice advice = advisor.getAdvice();
 6 
 7     //如果实现了MethodInterceptor则直接加入,比如AspectJAroundAdvice,AspectJAfterAdvice
 8     if (advice instanceof MethodInterceptor) 
 9         interceptors.add((MethodInterceptor) advice);
10     
11 
12     //否者看是否有当前advice的适配器,首先检验是否支持,支持则返回对应的适配器
13     for (AdvisorAdapter adapter : this.adapters) 
14         if (adapter.supportsAdvice(advice)) 
15             interceptors.add(adapter.getInterceptor(advisor));
16         
17     
18     if (interceptors.isEmpty()) 
19         throw new UnknownAdviceTypeException(advisor.getAdvice());
20     
21     return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
22 

 

以MethodBeforeAdviceAdapter为例子看下:

 1 class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable 
 2 
 3     public boolean supportsAdvice(Advice advice) 
 4         return (advice instanceof MethodBeforeAdvice);
 5     
 6 
 7     public MethodInterceptor getInterceptor(Advisor advisor) 
 8         MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
 9         return new MethodBeforeAdviceInterceptor(advice);
10     
11 
12 
13 
14 public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable 
15 
16     private MethodBeforeAdvice advice;
17 
18 
19     /**
20      * Create a new MethodBeforeAdviceInterceptor for the given advice.
21      * @param advice the MethodBeforeAdvice to wrap
查看详情  

常见开源协议详解(代码片段)

...该图乌克兰程序员PaulBagwell原创,阮一峰翻译)展示一下常用的开源协议:一、BSD(BerkeleySoftwareDistributionlicense)BSD源自加州大学伯克利分校,是自由软件中使用最广泛的许可协议之一,其给于使用者很大自由的协议。使用者可... 查看详情

聊聊mybatis的日志模块的适配器模式(代码片段)

...,而市场中有很多日志框架供我们使用,mybatis作为一个开源框架需要兼容这些框架,mybatis用了适配器模式来兼容这些框架,适配器模式就是通过组合的方式,将需要适配的类转为使用者能够使用的接口下面咱们分析一下mybatis的... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(七)一、项目介绍1、项目需求分析需求分析原因:可以整体的了解项目的业务流程和主要的业务需求。项目中,需求驱动开发。即开发人员需要以需求为目标来实现业务逻辑。需求分析... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(七)一、项目介绍1、项目需求分析需求分析原因:可以整体的了解项目的业务流程和主要的业务需求。项目中,需求驱动开发。即开发人员需要以需求为目标来实现业务逻辑。需求分析... 查看详情

一个开源分布式微服务rpc框架~正式发布(代码片段)

...发现和注销服务注册中心2.安全策略心跳机制信息摘要3.设计模式单例模式动态代理静态工厂建造者策略模式Future(观察者)亮点1.信息摘要算法的应用对于信息摘要算法的使用,其实并不难,在数据包中添加String类型的成员变量ch... 查看详情

headfirst设计模式分析学习(代码片段)

...弃的毅力,和对欲望的控制。注意:要能够理解相类似的设计模式之间的区别和不同。可以把类比列举出来,加深记忆。是否加入Spring容器中的标准是是否要用到Spring框架的方法或者功能特性,如事务,SpringMvc,与ibatis整合等相... 查看详情

开源web框架django知识总结(代码片段)

...django知识总结(十)异步方案Celery生产者消费者设计模式思考:下面两行代码存在什么问题?CCP().send_template_sms(mobile,[sms_code,5],1)returnJsonResponse('code':0,'errmsg':'ok')问题:我们的代码是自上而下... 查看详情

开源web框架django知识总结(代码片段)

...django知识总结(十)异步方案Celery生产者消费者设计模式思考:下面两行代码存在什么问题?CCP().send_template_sms(mobile,[sms_code,5],1)returnJsonResponse('code':0,'errmsg':'ok')问题:我们的代码是自上而下... 查看详情

如何正确使用开源项目?(代码片段)

...,并做好随时更新和发布新特性的准备1.使用成熟稳定的开源项目现在技术日新月异,可能隔几天就会出来一个新的开源框架,但是公司的商业项目永远以稳为主,也许你迫不及待的想尝鲜体验新技术,可以在你个人业余项目进... 查看详情

开源web框架django知识总结(十八)(代码片段)

开源web框架django知识总结(十八)商品详情页商品详情页分析和准备1.商品详情页组成结构分析1.商品频道分类封装在goods.utils.py文件中,直接调用方法即可。from.modelsimportGoodsCategory,GoodsChannel,SKUSpecification,SKU,SPUSpecificat... 查看详情

一个开源分布式微服务rpc框架~2.0版本问世(代码片段)

...发现和注销服务注册中心2.安全策略心跳机制信息摘要3.设计模式单例模式动态代理静态工厂建造者策略模式Future(观察者)亮点1.信息摘要算法的应用对于信息摘要算法的使用,其实并不难,在数据包中添加String类型的成员变量ch... 查看详情

anaconda中常用的用法(代码片段)

Anaconda中常用的用法conda是开源包(packages)和虚拟环境(environment)的管理系统。packages管理:可以使用conda来安装、更新、卸载工具包,并且它更关注于数据科学相关的工具包。在安装anaconda时就预先集成了像Numpy、Scipy、pandas、... 查看详情

模板方法模式(templatemethod)及应用(代码片段)

...法中的某些步骤。(来自百度百科)  模板方法模式在框架中经常使用,学习此模式后,对于阅读源码能力会有很大的提升。我准备先描述生活中的实际场景,引申出模板方式模式,然后分析此模式在JDK中的使用,最后分析在... 查看详情

模板方法模式:剖析模板方法在jdktomcatmybatis等开源框架中的应用(代码片段)

首发CSDN:徐同学呀,原创不易,转载请注明源链接。我是徐同学,用心输出高质量文章,希望对你有所帮助。文章目录一、模板方法定义二、通用写法三、模板方法在源码架构中的体现1、JDK中模板方法的体现... 查看详情

模板方法模式:剖析模板方法在jdktomcatmybatis等开源框架中的应用(代码片段)

首发CSDN:徐同学呀,原创不易,转载请注明源链接。我是徐同学,用心输出高质量文章,希望对你有所帮助。文章目录一、模板方法定义二、通用写法三、模板方法在源码架构中的体现1、JDK中模板方法的体现... 查看详情

ruoyi(若依开源框架)-前后端分离版-前端流程简单分析(代码片段)

RuoYi(若依开源框架)-前后端分离版-前端流程简单分析项目结构├──build//构建相关├──bin//执行脚本├──public//公共文件│├──favicon.ico//favicon图标│└──index.html//html模板├──src//源代码│├──api//所有请求│├──... 查看详情

betaflight模块设计之二十五:dispatch任务分析(代码片段)

...析dispatchProcess函数statsOnDisarm函数writeStats函数基于BetaFlight开源代码框架简介的框架设计,逐步分析内部模块功能设计。dispatch任务描述:目前从代码上看主要就是一个自动配置固化保存的例程。该例程主要功能就是di 查看详情