Nine classic design patterns in Spring

Simple factory (not one of 23 design modes)

Implementation method: BeanFactory. BeanFactory in Spring is the embodiment of the simple factory pattern. Bean objects are obtained by passing in a unique ID, but whether they are created after or before passing in parameters depends on the specific situation.
Essence: a factory class dynamically determines which product class should be created according to the passed in parameters.
Implementation principle:

  • Startup phase of bean container:

    • Read the xml configuration file of the bean and convert the bean elements into a BeanDefinition object.

    • Then register these beans in beanFactory through BeanDefinitionRegistry and save them in one of its concurrent hashmaps.

    • After registering BeanDefinition with beanFactory, Spring provides us with an extended notch here, allowing us to insert our defined code here by implementing the interface beanfactoryprocessor. A typical example is: PropertyPlaceholderConfigurer, which is the placeholder value we usually use when configuring the database dataSource.

 

  • The instantiation stage of beans in the container. The instantiation stage mainly instantiates beans through reflection or CGLIB. At this stage, Spring exposes many extension points to us:

    • Various Aware interfaces, such as BeanFactory Aware. For beans that implement these Aware interfaces, Spring will help us inject corresponding BeanFactory instances when instantiating beans.

    • The BeanPostProcessor interface is a bean that implements the BeanPostProcessor interface. When instantiating the bean, Spring will help us call the methods in the interface.

    • InitializingBean interface is a bean that implements the InitializingBean interface. When instantiating a bean, Spring will help us call the methods in the interface.

    • DisposableBean interface is a bean that implements the BeanPostProcessor interface. When the bean dies, Spring will help us call the methods in the interface.


Design significance:

  • Loose coupling. The original hard coded dependencies can be injected into dependencies through the foreman of Spring beanFactory, that is, there were only the relying party and the dependent party. Now we have introduced a third party, Spring beanFactory, to solve the dependency problem between beans and achieve the effect of loose coupling.

  • Additional processing of beans. Through the exposure of the spring interface, we can carry out some additional processing in the instantiation stage of the bean. These additional processing only needs to make the bean implement the corresponding interface, and then spring will call our implemented interface to process the bean in the bean life cycle.


Factory method

Implementation method: FactoryBean interface.

Implementation principle: beans that implement the FactoryBean interface are a class of beans called factory. The feature is that spring will automatically call the getObject() method of the bean when using getBean() call to obtain the bean, so the returned bean is not the factory bean, but the bean The return value of the getojbect () method.
example:

  • A typical example is the combination of Spring and MyBatis.

  • Code example:

  • Note: let's look at the bean above. Because it implements the FactoryBean interface, the returned SqlSessionFactoryBean is not an instance of SqlSessionFactoryBean, but its SqlSessionFactoryBean Return value of getobject().


Singleton mode

Spring dependency injection Bean instances are singleton by default.
Spring dependency injection (including lazy init mode) takes place in getBean of AbstractBeanFactory. The doGetBean method of getBean calls getSingleton to create a bean.
Analyze getSingleton() method:

public Object getSingleton(String beanName){
    //Parameter true sets the identifier to allow early dependencies
    return getSingleton(beanName,true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //Check whether there are instances in the cache
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        //If it is empty, the global variable is locked and processed.
        synchronized (this.singletonObjects) {
            //If this bean is loading, it will not be processed
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {  
                //When some methods need to be initialized in advance, the addSingleFactory method will be called to store the corresponding ObjectFactory initialization policy in singletonFactories
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //Call the preset getObject method
                    singletonObject = singletonFactory.getObject();
                    //Recorded in the cache, earlysingletonObjects and singletonFactories are mutually exclusive
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

getSingleton() process diagram (ps: Spring dependency injection uses the singleton module of double judgment locking

 

 

Singleton pattern definition: ensure that a class has only one instance and provide a global access point to access it.
Spring implementation of singleton: the singleton pattern in spring completes the second half sentence, that is, it provides a global access point BeanFactory. However, singletons are not controlled at the constructor level because spring manages arbitrary Java objects.

 

Adapter mode

 

 

Implementation method: the adapter HandlerAdatper in spring MVC.
Implementation principle: HandlerAdatper executes different handlers according to Handler rules.
Implementation process: DispatcherServlet sends a request to HandlerAdatper according to the handler returned by HandlerMapping to process the handler. The HandlerAdapter finds the corresponding handler according to the rules and lets it execute. After execution, the handler will return a ModelAndView to the HandlerAdapter, and finally the HandlerAdapter will return a ModelAndView to the dispatchservlet.
Implementation significance: HandlerAdapter makes it easy to extend the Handler. You only need to add a new Handler and a corresponding HandlerAdapter. Therefore, Spring defines an adaptation interface, so that each controller has a corresponding adapter implementation class, which allows the adapter to execute the corresponding methods instead of the controller. In this way, when extending the controller, you only need to add an adapter class to complete the extension of Spring MVC.

 

Decorator mode

 

Implementation method: the Wrapper pattern used in Spring has two manifestations in the class name: one is that the class name contains Wrapper, and the other is that the class name contains Decorator.
Substance:

  • Dynamically add some additional responsibilities to an object.

  • In terms of adding functions, the Decorator pattern is more flexible than generating subclasses.

 

proxy pattern

 

Implementation method: the bottom layer of AOP is the implementation of dynamic agent mode.

  • Dynamic proxy: it is built in memory and does not need to write proxy classes manually

  • Static proxy: the proxy class needs to be written manually, and the proxy class references the proxied object.


Implementation principle: the section is woven at the time of application operation. Generally, when weaving in the cut plane, the AOP container will dynamically create a proxy object for the target object. Spring AOP is woven into the section in this way.
Weaving: the process of applying facets to the target object and creating a new proxy object.

 

 

Observer mode

 

Implementation method: the event driven model of Spring uses Observer mode, and the common place of Observer mode in Spring is the implementation of listener.
Specific implementation: the implementation of event mechanism needs three parts: event source, event and event listener.
ApplicationEvent abstract class [event]
EventObject inherited from JDK. All events need to inherit ApplicationEvent, and the event source is obtained through the constructor parameter source.
The implementation class ApplicationContextEvent of this class represents the container event of ApplicaitonContext.
code:

public abstract class ApplicationEvent extends EventObject {
    private static final long serialVersionUID = 7099057708183571937L;
    private final long timestamp;
    public ApplicationEvent(Object source) {
    super(source);
    this.timestamp = System.currentTimeMillis();
    }
    public final long getTimestamp() {
        return this.timestamp;
    }
}

ApplicationListener interface [event listener]
Inheriting from the EventListener of JDK, all listeners should implement this interface.
This interface has only one onApplicationEvent() method. This method accepts an ApplicationEvent or its subclass object as a parameter. In the method body, you can process it according to different judgments on the Event class.
When the event is triggered, all listeners will receive a message.
code:

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

ApplicationContext interface [event source]
ApplicationContext is a global container in Spring, which translates to "application context".
Implements the ApplicationEventPublisher interface.
Responsibilities: be responsible for reading bean configuration documents, managing bean loading and maintaining dependencies between beans. It can be said to be responsible for the whole life cycle of beans. To put it more popularly, it is what we usually call IOC container.
code:

public interface ApplicationEventPublisher {
        void publishEvent(ApplicationEvent event);
}   

public void publishEvent(ApplicationEvent event) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
         logger.trace("Publishing event in " + getDisplayName() + ": " + event);
    }
    getApplicationEventMulticaster().multicastEvent(event);
    if (this.parent != null) {
    this.parent.publishEvent(event);
    }
}

Applicationeventmulticast abstract class [the publishEvent method in the event source needs to call its method getapplicationeventmulticast]
It belongs to the Event broadcaster. Its function is to broadcast the events published by Applicationcontext to all listeners.
code:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext, DisposableBean {  
    private ApplicationEventMulticaster applicationEventMulticaster;  
    protected void registerListeners() {  
    // Register statically specified listeners first.  
    for (ApplicationListener<?> listener : getApplicationListeners()) {  
    getApplicationEventMulticaster().addApplicationListener(listener);  
    }  
    // Do not initialize FactoryBeans here: We need to leave all regular beans  
    // uninitialized to let post-processors apply to them!  
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);  
    for (String lisName : listenerBeanNames) {  
    getApplicationEventMulticaster().addApplicationListenerBean(lisName);  
    }  
  }  
}

Strategy mode

 

Implementation method: Resource access interface of Spring framework. This interface provides stronger Resource access capability. The Spring framework itself makes extensive use of the Resource interface to access the underlying resources.
Resource interface introduction
The source interface is an abstraction of a specific resource access policy and an interface implemented by all resource access classes.
The Resource interface mainly provides the following methods:

  • getInputStream(): locate and open the resource and return the input stream corresponding to the resource. Each call returns a new input stream. The caller must be responsible for closing the input stream.

  • exists(): Returns whether the Resource pointed to by the Resource exists.

  • Ispen(): Returns whether the resource file is open. If the resource file cannot be read multiple times, it should be closed explicitly after each reading to prevent resource leakage.

  • getDescription(): returns the description information of the resource. It is usually used to output this information when there is an error in resource processing. It is usually a fully qualified file name or an actual URL.

  • getFile: returns the File object corresponding to the resource.

  • getURL: returns the URL object corresponding to the resource.


The last two methods do not need to be used. Only when simple access cannot be achieved, Resource provides the function of traditional Resource access.
The Resource interface itself does not provide implementation logic for accessing any underlying resources. For different underlying resources, Spring will provide different Resource implementation classes, which are responsible for different Resource access logic.
Spring provides the following implementation classes for the Resource interface:

  • UrlResource: implementation class for accessing network resources.

  • ClassPathResource: the implementation class that accesses the resources in the class loading path.

  • FileSystemResource: an implementation class that accesses resources in a file system.

  • ServletContextResource: an implementation class that accesses resources relative to the ServletContext path

  • InputStreamResource: the implementation class that accesses the input stream resource.

  • ByteArrayResource: implementation class to access byte array resources.


These Resource implementation classes provide corresponding Resource access logic for different underlying resources, and provide convenient packaging to facilitate the Resource access of client programs.

 

template method

 

Classic template method definition:
The parent class defines the skeleton (which methods and sequences to call), and some specific methods are implemented by the child class.
The biggest benefit: code reuse and reduce duplicate code. Except for the specific methods to be implemented by the subclass, other methods and method call sequences are written in advance in the parent class.
Therefore, there are two types of methods in the parent class template method:

    • Common method: code used by all subclasses

    • Different methods: the methods to be covered by subclasses are divided into two types:

      • Abstract method: the method in the parent class is an abstract method, and the subclass must be overridden

      • Hook method: the parent class is an empty method, and the subclass inherits the default method

         

Note: why is it called a hook? Subclasses can control the parent class through this hook (method), because this hook is actually the parent class's method (empty method)!

 

The essence of Spring Template Method pattern: it is the combination of Template Method pattern and callback pattern. It is another implementation method that Template Method does not need to inherit. Almost all Spring external extensions adopt this pattern.
Specific implementation: the abstraction of JDBC and the integration of Hibernate adopt a concept or processing method, that is, the combination of template method pattern and corresponding Callback interface.
The template method mode is adopted to handle the acquisition and release of resources in a unified and centralized way. Take JdbcTemplate as an example:

public abstract class JdbcTemplate {  
     public final Object execute(String sql){  
        Connection con=null;  
        Statement stmt=null;  
        try{  
            con=getConnection();  
            stmt=con.createStatement();  
            Object retValue=executeWithStatement(stmt,sql);  
            return retValue;  
        }catch(SQLException e){  
             ...  
        }finally{  
            closeStatement(stmt);  
            releaseConnection(con);  
        }  
    }   
    protected abstract Object executeWithStatement(Statement   stmt, String sql);  
}

Reason for introducing callback: JdbcTemplate is an abstract class and cannot be used independently. We need to give a corresponding subclass implementation every time we access data. This must be inconvenient, so callback is introduced.
Callback code:

public interface StatementCallback{  
    Object doWithStatement(Statement stmt);  
}

Override the JdbcTemplate method with the callback method:

public class JdbcTemplate {  
    public final Object execute(StatementCallback callback){  
        Connection con=null;  
        Statement stmt=null;  
        try{  
            con=getConnection();  
            stmt=con.createStatement();  
            Object retValue=callback.doWithStatement(stmt);  
            return retValue;  
        }catch(SQLException e){  
            ...  
        }finally{  
            closeStatement(stmt);  
            releaseConnection(con);  
        }  
    }  

    ...//Definition of other methods  
}

The usage of Jdbc is as follows:

JdbcTemplate jdbcTemplate=...;  
    final String sql=...;  
    StatementCallback callback=new StatementCallback(){  
    public Object=doWithStatement(Statement stmt){  
        return ...;  
    }  
}    
jdbcTemplate.execute(callback);

Why does the JdbcTemplate not use inheritance?
There are too many methods in this class, but we still want to use the existing stable and public database connection of JdbcTemplate. What should we do? We can extract the changed things and pass them into the method of JdbcTemplate as a parameter. But what changes is a piece of code, and this code will use the variables in the JdbcTemplate. What should I do? Let's use the callback object. Define a method to manipulate the variables in the JdbcTemplate in the callback object. Let's implement this method and concentrate the changed things here. Then we pass in the callback object to the JdbcTemplate to complete the call.
Original link: https://blog.csdn.net/caoxiaohong1005/article/details/80039656

 

Keywords: Spring Design Pattern

Added by Digimatt on Fri, 21 Jan 2022 04:21:26 +0200