Ali II: what design patterns does the Spring framework use?

1 simple factory mode

When object a needs to call the method of object B, we need to create a new instance of B in A. we call this method hard coding coupling. The disadvantage is that once the requirements change, such as using class C to replace B, we have to rewrite the method of class A.

If thousands of classes in the application are hard coded to couple B, it will be a headache.
Therefore, there is a simple factory mode, also known as static factory method. A factory class dynamically determines which product class should be created according to the incoming parameters.

BeanFactory in Spring is the embodiment of the simple factory pattern. BeanFactory is a core interface in the Spring IOC container. Its definition is as follows:

Bean can be obtained through its specific implementation class (such as ClassPathXmlApplicationContext):

BeanFactory bf = new ClassPathXmlApplicationContext("spring.xml");
User userBean = (User) bf.getBean("userBean");

Users do not need to create new by themselves, but get object instances through the method get Bean of the factory class. This is the simple factory pattern, but Spring creates beans with reflection.

2 factory method mode

In a simple factory, the factory class performs all logical judgment and instance creation.
If you don't want to judge in the factory class, you can provide different factories for different products. Different factories produce different products. Each factory corresponds to only one corresponding object. This is the factory method mode.

Spring FactoryBean

Define a class UserFactoryBean to implement the FactoryBean interface, mainly to create a new User object in the getObject method.
In this way, the User instance generated by the factory is obtained through getBean(id), not the UserFactoryBean itself:

BeanFactory bf = new ClassPathXmlApplicationContext("user.xml");
User userBean = (User) bf.getBean("userFactoryBean");

3. Singleton mode

Only one instance of a class is allowed during the operation of the whole system.

Spring beans are singleton mode by default. Spring uses the singleton Registry (HashMap) method:

public class DefaultSingletonBeanRegistry {
    
    // Use ConcurrentHashMap to save various single instance objects
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>;

    protected Object getSingleton(String beanName) {
    // Get the Object in the Map first
    Object singletonObject = singletonObjects.get(beanName);
    
    // If not, create an object instance through reflection and add it to HashMap
    if (singletonObject == null) {
      singletonObjects.put(beanName,
                           Class.forName(beanName).newInstance());
   }
   
   // Return object instance
   return singletonObjects.get(beanName);
  }
}

4 agent mode

It implements the same interface as the proxy object. The client must interact with the proxy target class through the proxy. The proxy generally performs some specific processing in the process of interaction (before and after interaction), such as pre-processing before calling this method and post-processing after calling this method.

benefit

Some common logic can be added based on the business functions of the target object. For example, if we want to add logging, permission management and transaction control functions to the target object, we can use the proxy class to complete it without modifying the target class, so as to maintain the stability of the target class.

Comply with the opening and closing principle, and do not modify the code or method written by others at will.

Agents are divided into

Static proxy

An interface needs to be defined. The proxy object (target object) and proxy object (Proxy) implement the same interface together:

// Abstract interface
public interface IStudentDao {
    void save();
}

// Target object
public class StudentDao implements IStudentDao {
    public void save() {
        System.out.println("Saved successfully");
    }
}

// Proxy object
public class StudentDaoProxy implements IStudentDao{
    //Holds a reference to the target object
    private IStudentDao target;
    public StudentDaoProxy(IStudentDao target){
        this.target = target;
    }

    //Add transaction control before and after the target function object method
    public void save() {
        System.out.println("Start transaction");
        target.save();//Method of executing target object
        System.out.println("Commit transaction");
    }
}

public static void main(String[] args) {
    //Create target object
    StudentDao target = new StudentDao();

    //Create a proxy object, transfer the target object to the proxy object, and establish a proxy relationship
    StudentDaoProxy proxy = new StudentDaoProxy(target);
   
    //The method of the agent is executed
    proxy.save();
}

Dynamic agent

Spring AOP adopts dynamic proxy, that is, the proxy class is dynamically created by the JVM when the program runs.
In the example of static proxy, the proxy class (StudentDaoProxy) is customized and has been compiled before the program runs.
The dynamic proxy class is not defined in Java code, but dynamically generated at runtime according to our "instructions" in Java code.

How to "instruct" JDK to dynamically generate proxy classes?

In Java Lang.reflect package provides a Proxy class and an InvocationHandler interface, through which dynamic Proxy objects can be generated:
1. Define an InvocationHandler class and put the logic to be extended into this class.
For example, the following example simulates adding transaction control:

public class MyInvocationHandler implements InvocationHandler {

    private Object obj;

    public MyInvocationHandler(Object obj){
        this.obj=obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        System.out.println("Start transaction");
        Object result = method.invoke(obj, args);
        System.out.println("Start transaction");
        
        return result;
    }
}
  1. Create proxy objects dynamically using Proxy#newProxyInstance
public static void main(String[] args) {
  //Create target object StudentDao
  IStudentDao stuDAO = new StudentDao();
  
  //Create MyInvocationHandler object
  InvocationHandler handler = new MyInvocationHandler(stuDAO);
  
  //Use proxy Newproxyinstance dynamically creates a proxy object stuProxy
  IStudentDao stuProxy = (IStudentDao) 
 Proxy.newProxyInstance(stuDAO.getClass().getClassLoader(), stuDAO.getClass().getInterfaces(), handler);
  
  //Method of using proxy object
  stuProxy.save();
}

The advantage of dynamic proxy is that it can easily handle the functions of proxy classes uniformly without modifying the methods in each proxy class.

Spring implements the method level aspect enhancement of the class through the dynamic proxy, that is, dynamically generate the proxy class of the target object, set the interceptor in the method of the proxy class, and enhance the function of the proxy method by executing the logic in the interceptor, so as to realize AOP.

Keywords: Design Pattern

Added by Smifffy on Tue, 04 Jan 2022 02:07:14 +0200