This is the first day of my participation in the August Text Challenge.More challenges in August

I. Factory design mode

1.1. Disadvantages of EJB, the traditional container

EJB (Enterprise Java Beans) is called Enterprise Java Beans. It was the container used by the previous generation. Let’s take a look at the traditional J2EE architecture.

EJB has a fatal disadvantage:

  1. The operating environment is harsh.
  2. Code portability is poor.
  3. EJB is a heavyweight framework.

1.2. What is Spring

Spring is a lightweight JavaEE solution that incorporates many excellent design patterns, the most important of which is the factory design pattern. It also includes other design patterns, such as the proxy design pattern, template design pattern, policy design pattern, and so on.

1.3. What is factory Design mode

In traditional object creation, we call the no-argument constructor to create the object in the new way, so that the degree of coupling (specifying that the code is strongly correlated, changes in one side will affect the other) is very high. ,

Once we need to change the type, we need to change it in the code, and recompile and deploy it.

1.4. Realization of factory design pattern

package com.factory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class BeanFactory {
    private static Properties env = new Properties();

    static{
        try {
            // The first step is to get the IO input stream
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            / / the second step encapsulates the Properties of the contents of the documents in the collection key = userService, value = com. Service. Impl. UserServiceImpl
            env.load(inputStream);
            inputStream.close();
        } catch(IOException e) { e.printStackTrace(); }}UserService UserService = new UserServiceImpl(); UserService = new UserServiceImpl(); 2. Through reflection can create the object in the form of decoupling Class clazz = Class. Class.forname (" com. Service. Impl. UserServiceImpl "); UserService userService = (UserService)clazz.newInstance(); * /
    public static UserService getUserService(a) {

        UserService userService = null;
        try {                 
            Class clazz = Class.forName(env.getProperty("userService"));
            userService = (UserService) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return userService;

    }

    public static UserDAO getUserDAO(a){

        UserDAO userDAO = null;
        try {
            Class clazz = Class.forName(env.getProperty("userDAO"));
            userDAO = (UserDAO) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        returnuserDAO; }}Copy the code
userDAO = com.dao.userDAO

userService = com.service.userService
Copy the code

1.5. Code modification of simple factory

We can find that a factory design pattern code above is long, every time we create a new object, all you need to write a factory class, and a large part of the code are the same, just create object is different, so we can extract the common code, of a generic factory classes.

public class BeanFactory{
  
    public static Object getBean(String key){
         Object ret = null;
         try {
             Class clazz = Class.forName(env.getProperty(key));
             ret = clazz.newInstance();
         } catch (Exception e) {
            e.printStackTrace();
         }
         returnret; }}Copy the code

1.6,

Spring is essentially a factory, but we don’t use the factory we wrote for our daily development. Because the factory has very few features and low performance, Spring helps us write a large factory (ApplicationContext). We just need to do this in a fixed configuration file (applicationContext.xml).

2. Getting started with Spring

2.1 Introduction to Spring

Spring is a lightweight Java development framework created in 2003 to address the complexities of enterprise application development. At the heart of Spring are inversion of Control (IoC) and section-oriented programming (AOP). Spring is a lightweight open source framework that can be used in Java SE/EE.

Spring’s main role is to “decouple” code, reducing the coupling between codes. The idea is to let the relationships between objects (modules and modules) be specified not using code associations, but through configuration. That is, the relationship of objects (modules) is explained in Spring.

Spring uses Ioc to decouple business objects based on the functional characteristics of the code. IoC removes the need for the main business to maintain its own relationship in the process of calling each other, that is, to create objects to use. Instead, it is managed by the Spring container and automatically “inject,” which means assign. AOP maximizes the reuse of system-level services, which are no longer manually “mixed” into the main business logic by programmers, but “woven” into it by the Spring container.

2.2. Advantages of Spring

Spring is a framework, a half-finished piece of software. It consists of 20 modules. It’s a container-managed object, containers are things, Spring containers don’t hold text, numbers. It’s an object. Spring is a container for storing objects. His advantages are mainly in the following aspects.

  1. Light weight.
  2. Interface oriented programming.
  3. Section-oriented programming
  4. Other excellent frameworks can be easily integrated.

2.2.1, lightweight

The Jars used by the Spring framework are small, typically under 1M or a few hundred KILobytes. The total number of jars required for Spring core functionality is around 3M. The Spring framework consumes fewer resources and runs efficiently. Do not rely on other jars.

2.2.2 Interface oriented programming

Spring provides Ioc inversion of control, container-managed objects, and object dependencies. The way objects were created in program code is now done by containers. Dependency decoupling between objects.

2.2.3 Aspect Oriented Programming (AOP)

The AOP functionality provided by Spring makes it easy to do section-oriented programming, and many functions that are not easy to implement with traditional OOP can be easily handled with AOP. In Spring, developers can be freed from the complex transaction management code and manage transactions flexibly in a declarative way, improving development efficiency and quality.

2.2.4. Integrate other excellent frameworks

Spring does not exclude great open source frameworks, but instead makes them easier to use. Spring provides direct support for great frameworks such as Shiro, MyBatis, and so on. Simplify the use of frameworks. Spring is like a plug board, and other frameworks are plugs that can be easily put together. Whichever frame you want to use, put this plug in the plugboard. It doesn’t need to be easily removed.

2.3. Spring architecture

Spring consists of more than 20 modules, They can be divided into Data Access/Integration, Web, aspect oriented programming (AOP, Aspects, Instrumentation, Messaging, Core Containers, and Tests.

2.4. Spring’s core API

At its heart, Spring is a big factory: ApplicationContext, which is used to create objects and can be uncoupled, is an interface, but ApplicationContext is a heavyweight factory object that takes up a lot of memory, so we don’t create objects very often, usually an application only creates one factory object. ApplicationContext is thread-safe and can be accessed concurrently by multiple threads.

He did it in two ways:

  1. For non-Web environments: ClassPathXmlApplication

  1. For WEB environments: XmlApplicationContext

2.5. Case of Spring

2.5.1 Introducing dependencies

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.5. RELEASE</version>
    </dependency>
Copy the code

2.5.3 Creation type

package com.domain;

/ * * *@author Xiao_Lin
 * @date2021/2/4 15:57 * /
public class Person {}Copy the code

2.5.4 Modify the configuration file

Change the configuration in the applicationContext.xml configuration file

<! -- id attribute: name -->
<! -- class attribute: fully qualified name of the object to be created -->
  <bean id="person" class="com.domain.Person"/>
Copy the code

2.5.5. Create an Object

  /** * used to test Spring's first program */
  @Test
  public void testSpring(a){
    // 1. Get the Spring factory
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
    // 2. Use the factory class to get the object
    Person person = (Person)applicationContext.getBean("person");
    System.out.println(person);
  }
Copy the code

2.6 Detailed analysis

2.6.1 Explanation of nouns

Spring factory creates objects called beans or components.

2.6.2. Related methods

// By obtaining objects in this way, no casts are required
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);
        

// Currently only one 
      
        tag in the Spring configuration file can have a class of type Person
      
Person person = ctx.getBean(Person.class);
System.out.println("person = " + person);
        

Person Person1 = person Person1 = person Person1 = person Person1
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
  System.out.println("beanDefinitionName = " + beanDefinitionName);
}
        

// Get the corresponding id value in the Spring configuration file based on the type
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {
  System.out.println("id = " + id);
}
        

// Determine whether a bean with the specified id exists
if (ctx.containsBeanDefinition("a")) {
  System.out.println("true = " + true);
}else{
  System.out.println("false = " + false);
}
      

// Check whether there is a bean with the specified id (name) value
if (ctx.containsBean("person")) {
  System.out.println("true = " + true);
}else{
  System.out.println("false = " + false);
}
Copy the code

2.7. Spring’s simple schematic for creating objects

Note: Reflection calls the no-argument constructor to instantiate the object, even if the constructor is private.

2.8, pay attention to

In future development, all objects will theoretically be created by the Spring factory, but there is a special class of objects — entity objects that Spring does not create are created by the persistence layer.

Three, injection

3.1. What is injection

Injection is when Spring creates an object and assigns its dependency properties to the object through configuration.

3.2. Why is injection needed

By encoding (setXxx), assigning values to member variables, there is coupling.

3.3. Method of injection

  1. Set injection: Its class must provide a corresponding setter method.
  2. Constructor injection: Injection using a constructor.

3.4. Set injection

package com.domain;

/ * * *@author Xiao_Lin
 * @date2021/2/4 15:57 * /
public class Person {
  private String username;
  private Integer password;


  @Override
  public String toString(a) {
    return "Person{" +
        "username='" + username + '\' ' +
        ", password=" + password +
        '} ';
  }

  public Person(String username, Integer password) {
    this.username = username;
    this.password = password;
  }

  public Person(a) {}public String getUsername(a) {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public Integer getPassword(a) {
    return password;
  }

  public void setPassword(Integer password) {
    this.password = password; }}Copy the code
<bean id="person" class="com.domain.Person">
    <property name="username">
      <value>Xiao_Lin</value>
    </property>
    <property name="password">
      <value>123456</value>
    </property>
  </bean>
Copy the code
/** * for test injection */
  @Test
  public void testDI(a){
    ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person = application.getBean("person", Person.class);
    System.out.println(person);
  }
Copy the code

3.4.1 Schematic diagram of SET injection

Spring assigns values to member variables by underlying calls to set methods corresponding to object attributes.

3.4.2 Detailed description of SET injection

For different types of member variables, we cannot always use the value tag, we need to nest other tags, we classify the possible types of member variables into two categories:

  1. Built-in JDK types.
  2. User-defined type.

3.4.2.1 built-in JDK types

3.4.2.1.1. String+8 Basic data types

Just use the value tag

<property name="password">
	<value>123456</value>
</property>
Copy the code
3.4.2.1.2. Array types

For array types, we need to use the list tag in our configuration file to indicate array types, and the nested value tag to do the assignment.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
  private String[] emails;
}

Copy the code
 <property name="emails">
      <list>
        <value>[email protected]</value>
        <value>[email protected]</value>
      </list>
    </property>
Copy the code
3.4.2.1.3. Set Set

For set types, we need to assign values in the configuration file using the set tag, indicating the set type, nested with the corresponding tag in the set generic.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
 private Set<String> tels;
}

Copy the code
<property name="tels">
      <set>
        <value>123456</value>
        <value>456789</value>
        <value>13579</value>
      </set>
    </property>
Copy the code

For the set set, because we specified the generic type as String, it is the eight basic data types, so the value tag is nested in the set tag. If no generics or other generics are specified, set nested tags need to be analyzed on a case-by-case basis.

3.4.2.1.4. List Collection

For the List collection type, we need to use the List tag in the configuration file, indicating the List collection type, to nest the corresponding tag in the List generic to perform the assignment.

What tags are nested in the List note depends on the generics in the list collection.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
 private List<String> address;
}
Copy the code
<property name="address">
      <list>
        <value>sz</value>
        <value>sz</value>
        <value>gz</value>
      </list>
    </property>
Copy the code
3.4.2.1.5. Map Collection

For the Map collection, there is an inner class called Entry, so the tag we need to use in the configuration file is to use the Map tag to nest the Entry tag, which encapsulates a pair of key-value pairs. We use the key label to represent the key, which contains the corresponding label of the key, and the value should be selected according to the corresponding type of label.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
 private Map<String,String> qq;
}
Copy the code
    <property name="qq">
      <map>
        <entry>
          <key><value>zs</value></key>
          <value>123456</value>
        </entry>
        <entry>
          <key><value>lisi</value></key>
          <value>456789</value>
        </entry>
      </map>
    </property>
Copy the code
3.4.2.1.6. Properties Collection

Properties is similar to a special Map in that its key and value must be strings.

In the configuration file, we use props tags, which are nested with prop tags. A prop is a key-value pair, and the keys are written in the key property and the values are written inside the tag.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
 private Properties properties;
}
Copy the code
   <property name="properties">
      <props>
        <prop key="username">admin</prop>
        <prop key="password">123456</prop>
      </props>
    </property>
Copy the code

3.4.2.2. Custom Types

3.4.2.2.1. The first injection method
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hobby {
  private String name;
}
Copy the code
    <property name="hobby">
      <bean class="com.domain.Hobby"/>
    </property>
Copy the code

We can see that the first injection method is to write a bean tag inside the property tag, which has obvious disadvantages:

  1. Configuration file code redundancy, when I have 10,000 classes that need to reference the same object, I need to write the same code 10,000 times.
  2. The injected objects are created multiple times, wasting (JVM) memory resources because EACH time I write onebeanThe tag means to create a new object.
3.4.2.2.2 Second injection mode

In view of the obvious shortcomings of the first injection method, we need to improve, so there is a second injection method, which is to create a copy of the object we need to inject in advance, who needs to reference it.

 <bean> 
	<property name="hobby">
      <ref bean="hobby"/>
    </property>
 </bean>
  <bean id="hobby" class="com.domain.Hobby">
    <property name="name">
      <value>admin</value>
    </property>
  </bean>
Copy the code

3.4.3 Simplified writing of SET injection

3.4.3.1 attribute-based simplification

JDK type injection

We can use the value attribute to simplify the value of the value tag, but only for the eight basic data types ➕Stirng.

<! -- The old way -->
<property name="name">
	<value>Xiao_Lin</value>
</property>

<! -- Simplified way -->
<property name="name" value="Xiao_Lin"/>
Copy the code

User-defined type of injection

We can use the ref attribute to simplify the value of the REF tag.

<! -- The old way -->
<property name="hobby">
	<ref bean="hobby"/>
</property>

<! -- Simplified way -->
<property name="hobby" ref="hobby"/>
Copy the code

3.4.3.2 Simplification based on the P-namespace

We can see that many of the bean label values are repetitive and redundant, so we can use the P-namespace to simplify things.

<! -- Built-in data types -->
<bean id="person" class="com.domain.Person" p:username="zs" p:password="123456" />

<! -- User-defined type -->
<bean id="hobbyBean" class="com.domain.Hobby"></bean>

<bean id="hobby" class="com.domain.Person" p:hobby-ref="hobbyBean"
Copy the code

3.5. Structure injection

Spring calls the constructor, which assigns values to member variables through the configuration file. If you want to use construct injection, you must provide a constructor with arguments.

Constructor injection uses the constructor-arg tag, and a constructor parameter is a pair of constructor-arg tags. The order and number must be the same as the construction parameters.

When constructor overloading occurs, we can control it by controlling the number of constructor-arGs. If there is an overload with the same number of constructor arguments (for example, the first constructor assigns name and the second constructor assigns type), we need to specify the type with the type attribute.

@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Hobby {
  private String name;
  private String type;
}

Copy the code
<bean id="hobbyBean" class="com.domain.Hobby"> <constructor-arg> <value>running</value> </constructor-arg> <constructor-arg> <value>dayily</value> </constructor-arg>  </bean>Copy the code
/** * for test construct injection */
  @Test
  public void testDI2(a){
    ClassPathXmlApplicationContext cxt =
        new ClassPathXmlApplicationContext("/applicationContext.xml");
    Hobby hobbyBean = cxt.getBean("hobbyBean", Hobby.class);
    System.out.println(hobbyBean);
  }
Copy the code

3.6. Inject summary

Inversion of Control (IOC) and Dependency Injection (DI)

4.1 Inversion of Control (IOC)

An IoC is an Inversion of Control. It refers to transferring the right to call objects, which are traditionally controlled directly by program code, to the container, through which objects are assembled and managed. Inversion of control is a transfer of control over an object from the program code itself to an external container. Through the container to achieve object creation, attribute assignment, dependency management.

Simply put, inversion of control is the transfer of control over member variable assignments from code to Spring factories and configuration files.

IoC is a concept, an idea, and it can be implemented in a variety of ways. The Spring framework implements IoC using dependency injection (DI).

4.2 Dependency Injection

Dependency: The classA class contains instances of classB and calls methods of classB in classA to complete functions. That is, classA has dependencies on classB.

Dependency Injection: When a class needs another class, the other class can be used as a member variable of its own class, and eventually injected (assigned) through the Spring configuration file. In simple terms, in the process of program running, if you need to call another object to assist, you do not need to create the called in the code, but rely on the external container, created by the external container and passed to the program.

Spring’s dependency injection has few requirements on callers and callees and fully supports the management of dependencies between objects.

4.3,

The Spring container is a mega-factory that creates and manages all the Java objects, called beans. The Spring container manages the dependencies between beans in the container, and Spring uses dependency injection to manage the dependencies between beans. Use IoC to achieve decoupling and between objects.