Spring which are used in the design pattern invasion deleted

Source: https://mp.weixin.qq.com/s/O_iaG4ykKrNv6c73HhOYmw

JDK those used in design patterns? Spring used in those design patterns? These two issues, more common in the interview. I search the Internet for a moment to explain design patterns for Spring are almost stereotyped, and most are age-old. So, it took a few days to himself summed up what limited my personal capacity, the paper if you can point out any errors. In addition, article length is limited, for the interpretation of some of the design patterns and source code I just alluded to, the main purpose of this article is to review the common design pattern Spring.

Design Patterns (design mode) is object-oriented software development best practices computer programming. Spring Framework makes extensive use of different types of design patterns, let's look at what design pattern in the end?

Inversion of Control (IoC) and dependency injection (DI)

IoC (Inversion of Control, control flip)  is Spring in a very, very important concept, it is not a technology, but a decoupled design. Its main purpose is to achieve decoupling between objects having dependency by means of "third party" (Spring container in the IOC) (the IOC easy to manage objects, you can just use), thereby reducing the coupling between the code . IOC is a principle, instead of a pattern, the following modes (but not limited to) the IoC principle achieved.

 

ioc-patterns

 

Spring IOC container are like a factory, when we need to create an object, you can just configure the configuration file / annotation can be, no need to consider how objects are created out of.  IOC container is responsible for creating objects, connect objects together, configure these objects, and to process the entire lifecycle from the creation of these objects until they are completely destroyed.

In a real project a Service class if there are hundreds or even thousands of class as its bottom, we need to instantiate the Service, you may want to find out every time the constructor of this Service all the underlying class, which could put people crazy. If the use of the IOC, you only need to configure, and where necessary quoted on the line, which greatly increases the maintainability of the project and reduce the development effort. About Spring IOC understanding, it is recommended to see which look almost know one answer: https: //www.zhihu.com/question/23277575/answer/169698662, very good.

? Control Flip how to understand it  give an example: "Object a dependent object b, when the object is a need to use the object b must be to create their own but when the system was introduced IOC container, before the object a and object b lost. a direct link. this time, when the object is a need to use the object b, we can specify the IOC container to create an object b injected into a subject in. " The process of obtaining a target dependent objects b by the proactive behavior becomes a passive behavior, control of the flip, the origin of which is to control the reversal of the name.

DI (Dependecy Inject, dependency injection) is controlled to achieve a design pattern is inverted, that is the instance variable dependency injection into an object to pass.

Factory design pattern

Spring can use the factory pattern  BeanFactory or  ApplicationContext create a bean object.

Comparison between the two:

  • BeanFactory : Delayed implantation (when using the bean will be injected to a), compared to BeanFactorywho will take up less memory, programs start faster.

  • ApplicationContext : Container startup, whether you use to useless, disposable create all bean. BeanFactory Provides only the most basic dependency injection support, ApplicationContext expanded  BeanFactory , in addition to BeanFactoryfeatures include additional more features, it is generally developers ApplicationContextwill be more.

ApplicationContext realization of three categories:

  1. ClassPathXmlApplication: Document as the context classpath resources.

  2. FileSystemXmlApplication: Loaded from the file system XML file context definition information.

  3. XmlWebApplicationContext: Load context definition information from the Web system in XML files.

Example:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new FileSystemXmlApplicationContext(
                "C:/work/IOC Containers/springframework.applicationcontext/src/main/resources/bean-factory-config.xml");

        HelloApplicationContext obj = (HelloApplicationContext) context.getBean("helloApplicationContext");
        obj.getMsg();
    }
}

Singleton design pattern

In our system, there are some objects in fact, we only need one, for example: the thread pool, cache, dialog, registry, log object, the object serves as a device driver for your printer, graphics and so on. In fact, this type of object can only have one instance, if you create multiple instances of it could lead to some problems, such as: abnormal behavior of the program, and the resource overage, or inconsistency of the results.

The benefits of using Singleton pattern:

  • For frequently used objects, you can create omit the time it takes an object, which for those heavyweight objects, is very respectable amount of system overhead;

  • Due to the reduced number of new operations, and thus the frequency of use of system memory will be reduced, which will relieve pressure GC, GC pause times shortened.

The default scope in Spring bean is singleton (single example).  In addition to the singleton scope, Spring bean in scope as well as the following categories:

  • prototype: every request to create a new bean instance.

  • request: Each HTTP request will generate a new bean, which is only valid in the current HTTP request.

  • session: Each HTTP request will generate a new bean, which is only valid in the current HTTP session.

  • global-session: the global session scope, only the portlet web-based application makes sense, Spring5 gone. Portlet is capable of generating a semantic code (eg: HTML) Small Java Web plugin fragments. They are based portlet container may be treated as HTTP servlet request like. However, the servlet different, each has a different portlet session

Example implementations of a single Spring:

  • xml:<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>

  • annotation:@Scope(value = "singleton")

Spring by  ConcurrentHashMap single-mode specific embodiments manner singleton registry. Example Spring single-core code is as follows:

// 通过 ConcurrentHashMap(线程安全) 实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized (this.singletonObjects) {
            // 检查缓存中是否存在实例  
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                //...省略了很多代码
                try {
                    singletonObject = singletonFactory.getObject();
                }
                //...省略了很多代码
                // 如果实例对象在不存在,我们注册到单例注册表中。
                addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }
    //将对象添加到单例注册表
    protected void addSingleton(String beanName, Object singletonObject) {
            synchronized (this.singletonObjects) {
                this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));

            }
        }
}

Proxy design pattern

Application proxy mode in the AOP

AOP (Aspect-Oriented Programming: Oriented Programming) can be those regardless of the service, but a logical or liabilities (such as transaction processing, log management, access control, etc.) service module jointly called packaged to facilitate code duplication reduction system , to reduce the coupling between modules, and facilitate future scalability and maintainability.

Spring AOP is the dynamic agent-based , if you want to proxy object implements an interface, then Spring AOP will use JDK Proxy , to create a proxy object, but the object does not implement an interface, you can not use the JDK Proxy to proxy the this time Spring AOP uses Cglib  , this time Spring AOP uses  Cglib  generating a subclass of the object as a proxy agent, as shown below:

 

SpringAOPProcess

 

Of course, you can also use AspectJ, Spring AOP has been integrated with AspectJ, AspectJ should be counted on the Java ecosystem is the most complete of the AOP framework.

After using AOP we can put some common functions abstracted, use can be used directly where it is needed, which greatly simplifies the code amount. It is also convenient when we need to add new features, which would also increase the scalability of the system. Logging, transaction management, and so on scene have used the AOP.

Spring AOP and AspectJ AOP What is the difference?

Enhanced belonging run Spring AOP, and AspectJ is an enhanced compilation.  Spring AOP based agent (Proxying), based on the AspectJ bytecode manipulation (Bytecode Manipulation).

Spring AOP has been integrated with AspectJ, AspectJ should be counted on the Java ecosystem is the most complete of the AOP framework. Spring AOP AspectJ compared to the more powerful, but Spring AOP relatively more simple,

If we cut surface is relatively small, so little performance difference between the two. However, when cut too much, the best choice for AspectJ, it is much faster than Spring AOP.

Template Method

Template Method design pattern is a behavioral pattern that defines a skeleton of the algorithm operation, some steps to subclasses delay. Template Method lets subclasses may not change the structure of an algorithm to redefine certain steps of the implementation of the algorithm.

 

Template Method UML diagrams

 

public abstract class Template {
    //这是我们的模板方法
    public final void TemplateMethod(){
        PrimitiveOperation1();  
        PrimitiveOperation2();
        PrimitiveOperation3();
    }

    protected void  PrimitiveOperation1(){
        //当前类实现
    }

    //被子类实现的方法
    protected abstract void PrimitiveOperation2();
    protected abstract void PrimitiveOperation3();

}
public class TemplateImpl extends Template {

    @Override
    public void PrimitiveOperation2() {
        //当前类实现
    }

    @Override
    public void PrimitiveOperation3() {
        //当前类实现
    }
}

In Spring  jdbcTemplate, hibernateTemplate or the like to the end of the class Template database operations, they are used to model the template. Under normal circumstances, we are achieved using template inheritance pattern of the way, but Spring does not use this method, but using Callback Mode and Template Method pattern fit only achieve the effect of code reuse, as well as increased flexibility .

Observer Pattern

The observer pattern is an object behavioral patterns. It indicates the kind of object having a dependency between the object and, when an object is changed, the object of the dependent object will respond. Spring event-driven model is the Observer pattern of a classic application. Spring event-driven model is very useful in many scenarios can decouple our code. For example, every time we add commodities when they are required to re-update commodity index, this time we can use the observer pattern to solve this problem.

Spring event-driven model of the three roles

Events role

ApplicationEvent ( org.springframework.contextRole under the package) to act as an event, this is an abstract class that inherits java.util.EventObjectand implements  java.io.Serializablethe interface.

Spring 中默认存在以下事件,他们都是对 ApplicationContextEvent 的实现(继承自ApplicationContextEvent):

  • ContextStartedEventApplicationContext 启动后触发的事件;

  • ContextStoppedEventApplicationContext 停止后触发的事件;

  • ContextRefreshedEventApplicationContext 初始化或刷新完成后触发的事件;

  • ContextClosedEventApplicationContext 关闭后触发的事件。

 

ApplicationEvent-Subclass

 

事件监听者角色

ApplicationListener 充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()方法来处理ApplicationEventApplicationListener接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 ApplicationEvent就可以了。所以,在 Spring中我们只要实现 ApplicationListener 接口实现 onApplicationEvent() 方法即可完成监听事件

package org.springframework.context;
import java.util.EventListener;
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E var1);
}

事件发布者角色

ApplicationEventPublisher 充当了事件的发布者,它也是一个接口。

@FunctionalInterface
public interface ApplicationEventPublisher {
    default void publishEvent(ApplicationEvent event) {
        this.publishEvent((Object)event);
    }

    void publishEvent(Object var1);
}

ApplicationEventPublisher 接口的publishEvent()这个方法在AbstractApplicationContext类中被实现,阅读这个方法的实现,你会发现实际上事件真正是通过ApplicationEventMulticaster来广播出去的。具体内容过多,就不在这里分析了,后面可能会单独写一篇文章提到。

Spring 的事件流程总结

  1. 定义一个事件: 实现一个继承自 ApplicationEvent,并且写相应的构造函数;

  2. 定义一个事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法;

  3. 使用事件发布者发布消息: 可以通过 ApplicationEventPublisher 的 publishEvent() 方法发布消息。

Example:

// 定义一个事件,继承自ApplicationEvent并且写相应的构造函数
public class DemoEvent extends ApplicationEvent{
    private static final long serialVersionUID = 1L;

    private String message;

    public DemoEvent(Object source,String message){
        super(source);
        this.message = message;
    }

    public String getMessage() {
         return message;
          }


// 定义一个事件监听者,实现ApplicationListener接口,重写 onApplicationEvent() 方法;
@Component
public class DemoListener implements ApplicationListener<DemoEvent>{

    //使用onApplicationEvent接收消息
    @Override
    public void onApplicationEvent(DemoEvent event) {
        String msg = event.getMessage();
        System.out.println("接收到的信息是:"+msg);
    }

}
// 发布事件,可以通过ApplicationEventPublisher  的 publishEvent() 方法发布消息。
@Component
public class DemoPublisher {

    @Autowired
    ApplicationContext applicationContext;

    public void publish(String message){
        //发布事件
        applicationContext.publishEvent(new DemoEvent(this, message));
    }
}

当调用 DemoPublisher 的 publish() 方法的时候,比如 demoPublisher.publish("你好") ,控制台就会打印出:接收到的信息是:你好 。

适配器模式

适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。

spring AOP中的适配器模式

我们知道 Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter 。Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return之前)等等。每个类型Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptorAfterReturningAdviceAdapterAfterReturningAdviceInterceptor。Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象(如:MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice)。

spring MVC中的适配器模式

在Spring MVC中,DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。

为什么要在 Spring MVC 中使用适配器模式? Spring MVC 中的 Controller 种类众多,不同类型的 Controller 通过不同的方法来对请求进行处理。如果不利用适配器模式的话,DispatcherServlet 直接获取对应类型的 Controller,需要的自行来判断,像下面这段代码一样:

if(mappedHandler.getHandler() instanceof MultiActionController){  
   ((MultiActionController)mappedHandler.getHandler()).xxx  
}else if(mappedHandler.getHandler() instanceof XXX){  
    ...  
}else if(...){  
   ...  
}  

假如我们再增加一个 Controller类型就要在上面代码中再加入一行 判断语句,这种形式就使得程序难以维护,也违反了设计模式中的开闭原则 – 对扩展开放,对修改关闭。

装饰者模式

装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。其实在 JDK 中就有很多地方用到了装饰者模式,比如 InputStream家族,InputStream 类下有 FileInputStream (读取文件)、BufferedInputStream (增加缓存,使读取文件速度大大提升)等子类都在不修改InputStream 代码的情况下扩展了它的功能。

 

装饰者模式示意图

 

Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源。我们能否根据客户的需求在少修改原有类的代码下动态切换不同的数据源?这个时候就要用到装饰者模式(这一点我自己还没太理解具体原理)。Spring 中用到的包装器模式在类名上含有 Wrapper或者 Decorator。这些类基本上都是动态地给一个对象添加一些额外的职责

总结

Spring 框架中用到了哪些设计模式:

  • 工厂设计模式 : Spring使用工厂模式通过 BeanFactoryApplicationContext 创建 bean 对象。

  • 代理设计模式 : Spring AOP 功能的实现。

  • 单例设计模式 : Spring 中的 Bean 默认都是单例的。

  • 模板方法模式 : Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

  • 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。

  • 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller

  • ……

参考

  • 《Spring技术内幕》

  • https://blog.eduonix.com/java-programming-2/learn-design-patterns-used-spring-framework/

  • http://blog.yeamin.top/2018/03/27/单例模式-Spring单例实现原理分析/

  • https://www.tutorialsteacher.com/ioc/inversion-of-control

  • https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html

  • https://juejin.im/post/5a8eb261f265da4e9e307230

  • https://juejin.im/post/5ba28986f265da0abc2b6084

 

(完)

Guess you like

Origin blog.csdn.net/qq_22167989/article/details/94592110