Spring learning note 1 - IOC container I (IOC container, DI dependency injection)

Portal - > official documents

The significance of this note I made here is only to record my first experience in Spring. It is not an in-depth explanation of the official API, nor is it necessarily a novice friendly and detailed learning list of knowledge points.
To sum up, don't spray if you don't like it, but if you have any questions, please communicate in the comment area!

1.1 introduction to spring IOC container and Bean

1.1.1 Bean

What is Bean?

In Spring, the objects that form the backbone of the application and are managed by the Spring IoC container are called beans. Bean is created by Spring
IoC container instantiates, assembles and manages objects.

Obviously, beans here are not just those entity classes, namely POJO s. The Bean here contains all instances of Java classes managed by Spring!

Bean s and their dependencies are reflected in the Configuration Metadata used by the container.

The configuration metadata here is often used xml file or Java annotation implementation. We'll see concrete examples right away.

1.1.2 IOC container

The container that helps us manage Java objects is called the Spring IOC container.

At org springframework. Beans and org springframework. The context package is the foundation of the IoC container of the Spring framework

  • Their maven dependencies are
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>

1.2 vessel overview

org. springframework. context. The ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring and assembling beans.
The container obtains instructions about which objects to instantiate, configure and assemble by reading the configuration metadata. The configuration metadata is represented by XML, Java annotation or Java code.

Note that ApplicationContext is an interface, which usually creates ClassPathXmlApplicationContext or an instance of FileSystemXmlApplicationContext (as the name suggests, one through the classpath and one through the system file name).

1.2.1 configuration metadata

The Spring IoC container uses a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble objects in your application.

Here, metadata metadata actually indicates how objects are created, assembled and managed. (otherwise, how can Spring create the object we want according to our wishes?).

  • Form of configuration
    • XML
      This is also the most traditional way, that is, the so-called XML with Bean
    • annotation
      Annotation based configuration: Spring 2.5 introduces support for annotation based configuration metadata.
    • Java based configuration
      (this is supported from spring 3.0)

The configuration based on annotations and Java is the product of the later development of Spring. Here we take the most traditional XML as an example.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

Where id is the unique representation of defining a single Bean, and class should use the fully qualified name (unless the following alias is used).

1.2.2 instantiation container

In order to simplify the learning notes, the complete code is not provided here. For the specific code, see This blog.

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

1.2.3 use of containers

We can use ApplicationContext to access objects hosted by IOC containers.

  • Mode 1
T getBean(String name)
User user = (User)applicationContext.getBean("user");
  • Mode 2
T getBean(String name, Class<T> requiredType)
User user = applicationContext.getBean("user",User.class);

In summary, method 1 uses type coercion and method 2 uses type as parameter. Errors can be found during compilation, which is better.

1.3 Bean

1.3.1 naming of beans

  • Naming convention
    Use hump naming, such as accountManager, accountService, userDao, loginController.

  • Identification of Bean

<bean id="user" name="user2,user3,user4" class="com.jsy.pojo.User">
        <property name="name" value="JSY"></property>
    </bean>

Use id to uniquely identify the bean. name is an alias and can have multiple names@ Bean
Annotations can also provide aliases.

<bean id="user" name="user2,user3,user4" class="com.jsy.pojo.User">
 </bean>
  • No name provided
    Why is this allowed? You can guess that it is similar to anonymous inner classes without providing a name.
    This is related to the automatic assembly later.

1.3.2 Bean instantiation

This part is related to class initialization, not to mention

1.4 Dependencies

A typical enterprise application does not contain a single object (or bean in Spring terminology). Even in the simplest applications, there are objects that can work together to present applications that end users see as consistent.

In short, the composition of objects often depends on multiple other objects. For example, the Zoo instance depends on Tiger and Lion instances; UserService instance depends on UserDao or UserMapper instance.

Using DI principle, the code is more concise, and decoupling is more effective when providing dependencies for objects. The object does not look for its dependencies and does not know the location or class of the dependencies.

That is, programmers are no longer responsible for the creation and assembly of objects, but only for the provision of objects. The creation and assembly (DI) is completed by Spring.

To sum up, DI is actually a measure to realize IOC.

1.4.1 dependency injection

1.4.1.1 Constructor injection

Entity class

package com.jsy.pojo;

public class Zoo {
    Tiger tiger;
    Lion lion;

    public Zoo(Tiger tiger, Lion lion) {
        this.tiger = tiger;
        this.lion = lion;
    }
}

    <bean id="zoo" class="com.jsy.pojo.Zoo">
        <constructor-arg ref="lion"></constructor-arg>
        <constructor-arg ref="tiger"></constructor-arg>
    </bean>

    <bean id="lion" class="com.jsy.pojo.Lion"></bean>
    <bean id="tiger" class="com.jsy.pojo.Tiger"></bean>
  • Constructor parameter parsing matches by using the type of the parameter

In the above example, Lion and Tiger classes are not associated through inheritance, there is no potential ambiguity, and the configuration takes effect,

(the following example is from the official)

  • type attribute
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
  • index attribute
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
  • name attribute
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

1.4.1.2 Setter injection

Setter based DI is accomplished by calling the setter method on your bean after calling the parameterless constructor or parameterless static factory method to instantiate your bean.

  • Must have a parameterless constructor
  • There must be a set function. The function name is set + attribute name (initial capital)

1.4.1.3 Factory method injection

This method is consistent with the above two principles and has little difference.

public class ExampleBean {

    // a private constructor
    private ExampleBean(...) {
        ...
    }

    // a static factory method; the arguments to this method can be
    // considered the dependencies of the bean that is returned,
    // regardless of how those arguments are actually used.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }
}
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

Instance (non static) factory methods can be used in essentially the same way (except that the factory bean attribute is used instead of the class attribute)

1.4.1.4 circular dependency

package com.jsy.pojo;
public class A {
    B b;

    public void setB(B b) {
        this.b = b;
    }
}

package com.jsy.pojo;
public class B {
    A a;

    public void setA(A a) {
        this.a = a;
    }
}


Using constructor injection may create unresolved circular dependency schemes
One possible solution is to edit the source code of certain classes, which are configured by setters rather than constructors. Alternatively, avoid constructor injection and use only setter injection. In other words, although this is not recommended, you can configure circular dependencies using setter injection.

In short, if circular dependency occurs, setter injection must be used.

    <bean id="a" class="com.jsy.pojo.A">
        <property name="b" ref="b"></property>
    </bean>

    <bean id="b" class="com.jsy.pojo.B">
        <property name="a" ref="a"></property>
    </bean>

1.4.2 details of dependency injection

setter injection uses < property / >
The < constructor Arg / > element is used for constructor injection

The following is mainly the explanation of setter injection.

1.4.2.1 true value injection

    <bean id="student" class="com.jsy.pojo.Student">
        <property name="age" value="18"></property>
        <property name="name" value="Mike"></property>
    </bean>

1.4.2.2 Bean injection

    <bean id="zoo" class="com.jsy.pojo.Zoo">
        <property name="lion" ref="lion"></property>
       	<property name="tiger" ref="tiger"></property>
    </bean>

1.4.2.3 empty string and NULL

<bean class="ExampleBean">
    <property name="email" value=""/>
</bean>
<bean class="ExampleBean">
    <property name="email"><null/></property>
</bean>

The following example is from Kuangshen

1.4.2.4 array injection

 <bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="Xiao Ming"/>
     <property name="address" ref="addr"/>
     <property name="books">
         <array>
             <value>Journey to the West</value>
             <value>The Dream of Red Mansion</value>
             <value>Water Margin</value>
         </array>
     </property>
 </bean>

1.4.2.5 injection

<property name="hobbys">
     <list>
         <value>listen to the music</value>
         <value>watch movie</value>
         <value>Mountain climbing</value>
     </list>
 </property>

1.4.2.6 Map injection

 <property name="card">
     <map>
         <entry key="China Post" value="456456456465456"/>
         <entry key="build" value="1456682255511"/>
     </map>
 </property>

1.4.2.7 Set injection

<property name="games">
     <set>
         <value>LOL</value>
         <value>BOB</value>
         <value>COC</value>
     </set>
 </property>

1.4.2.8 Properties injection

 <property name="info">
     <props>
         <prop key="Student number">20190604</prop>
         <prop key="Gender">male</prop>
         <prop key="full name">Xiao Ming</prop>
     </props>
 </property>

1.4.2.9 p-namespace and c-namespace

  • p-space
    Depends on the setter method.
 Import constraints in header file : xmlns:p="http://www.springframework.org/schema/p"
 
 <!--P(attribute: properties)Namespace , Property should still be set set method-->
 <bean id="user" class="com.jsy.pojo.User" p:name="jsy" p:spouse-ref="address"/>
  • c-space
    Constructor dependent
 Import constraints : xmlns:c="http://www.springframework.org/schema/c"
 <!--C(structure: Constructor)Namespace , Property should still be set set method-->
 <bean id="user" class="com.jsy.pojo.User" c:name="jsy" c:age="18"/>

1.4.2.10 compound attribute name

<bean id="something" class="things.ThingOne">
    <property name="fred.bob.sammy" value="123" />
</bean>

This is equivalent to using attributes recursively all the time.

1.4.3 depends-on

In addition to using the < ref > element to represent the dependencies of bean s,
The dependencies on attribute that can be displayed:

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

1.4.4 lazy loading of beans

By default, the ApplicationContext implementation creates and configures all singleton bean s during initialization.

If you do not want to use this behavior, you can prevent pre instantiation of singleton beans by marking the bean definition as delayed initialization. Delayed initialization beans tell the IoC container to create a bean instance on the first request rather than on startup.

Use the lazy init attribute.

<!-- Default -->
<bean name="not.lazy" class="com.something.AnotherBean"/>
<!-- Lazy loading -->
<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>

1.4.5 automatic assembly

It is not intended to talk about the automatic assembly based on xml in spring, but the automatic assembly based on annotation, so it is omitted.

1.4.6 injection method

Method injection is an advanced function of Spring IoC container, which is omitted here.

Here's why method injection is needed.

Simply put, there are many problems caused by the different declaration cycles of beans. For example, a singleton bean depends on a prototype bean, but the property injection of a singleton bean has only one chance, which leads to a problem.

Tags: Java

Posted by spookztar on Sun, 08 May 2022 02:07:12 +0300