Spring from getting started to source code - basic use of IOC

1,spring_helloworld

Use maven to build the project (Mavaen)

  • Add the corresponding pom dependency
    pom.xml
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
    </dependencies>
  • Write code
    Person.java
  public class Person {
      private int id;
      private String name;
      private int age;
      private String gender;
  
      public int getId() {
          return id;
      }
  
      public void setId(int id) {
          this.id = id;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public int getAge() {
          return age;
      }
  
      public void setAge(int age) {
          this.age = age;
      }
  
      public String getGender() {
          return gender;
      }
  
      public void setGender(String gender) {
          this.gender = gender;
      }
  
      @Override
      public String toString() {
          return "Person{" +
                  "id=" + id +
                  ", name='" + name + '\'' +
                  ", age=" + age +
                  ", gender='" + gender + '\'' +
                  '}';
      }
  }
  • test

    MyTest.java

 public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
        Person person = (Person) context.getBean("person");
        System.out.println(person);
    }
 }

Summary:

  1. Be sure to add the configuration file to the classpath and put it in the resource directory when creating a project using idea
  2. When creating an object to assign values to attributes, it is implemented through the setter method
  3. Objects are singleton when stored in the IOC container. If multiple instances are needed, the properties need to be modified (the default singleton can be changed to multiple instances)
  4. The object is created when the Spring container is created, not when it needs to be used (the object is created when the Application is created)
  5. ApplicationContext is the interface of the IOC container. You can obtain the objects created in the container through this object

2. spring object acquisition and attribute assignment method

1. Get the object in the IOC container through the id of the bean (used above)

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
    id Object unique identifier
    class Class name: fully qualified name
-->
   <bean id = "person" class="com.yao.bean.Person">
       <property name="id" value="001"/>
       <property name="name" value="yzh"/>
       <property name="age" value="12"/>
       <property name="gender" value="man"/>
   </bean>

</beans>

2. Get the object by the type of the bean

        ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
        Person bean = context.getBean(Person.class);
        System.out.println(bean);

Note: when searching for objects through bean types, two bean objects with the same type cannot exist in the configuration file. If any, you can use the following methods

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
            Person person = context.getBean("person", Person.class);
            System.out.println(person);
        }
    }

3. Assign a value to the bean object through the constructor

Summary:

  • Constructor Arg adds a constructor to the person class
  • When using constructor assignment, you can omit the name attribute, but at this time, you must fill it in strict accordance with the order of constructor parameters
  • If you want to add parameter values out of order, you can use it with the index attribute
  • When there are multiple constructors with the same number of parameters and different types, the type can be enforced through type
  • Two overloaded construction methods. The latter construction method overrides the former construction method.
constructor-arg Five attribute values in:
value:assignment
name: Member properties
ref :adopt ref Reference other objects, reference external bean
index: If you want to add parameter values out of order, you can match them index Property to use
type: When there are multiple constructors of different types with the same number of parameters, you can type To force the type

ioc.xml

	<!--to person Class add constructor-->
	<bean id="person2" class="com.mashibing.bean.Person">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="lisi"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
        <constructor-arg name="gender" value="female"></constructor-arg>
        </bean>

	<!--It can be omitted when using constructor assignment name Property, but at this time, it is required to fill in strictly in the order of constructor parameters-->
	<bean id="person3" class="com.mashibing.bean.Person">
        <constructor-arg value="1"></constructor-arg>
        <constructor-arg value="lisi"></constructor-arg>
        <constructor-arg value="20"></constructor-arg>
        <constructor-arg value="female"></constructor-arg>
        </bean>

	<!--If you want to add parameter values out of order, you can match them index Property to use-->
      <bean id="person4" class="com.mashibing.bean.Person">
          <constructor-arg value="lisi" index="1"></constructor-arg>
          <constructor-arg value="1" index="0"></constructor-arg>
          <constructor-arg value="female" index="3"></constructor-arg>
          <constructor-arg value="20" index="2"></constructor-arg>
      </bean>
	<!--When there are multiple constructors of different types with the same number of parameters, you can type To force the type-->
	take person of age Type set to Integer type
	public Person(int id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
        System.out.println("Age");
    }
	// The latter construction method overrides the previous construction method.
    public Person(int id, String name, String gender) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        System.out.println("gender");
    }
	<bean id="person5" class="com.mashibing.bean.Person">
        <constructor-arg value="1"></constructor-arg>
        <constructor-arg value="lisi"></constructor-arg>
        <constructor-arg value="20" type="java.lang.Integer"></constructor-arg>
    </bean>
	<!--If not, change to integer Type, then you need type Follow index Combined use-->
	 <bean id="person5" class="com.mashibing.bean.Person">
        <constructor-arg value="1"></constructor-arg>
        <constructor-arg value="lisi"></constructor-arg>
        <constructor-arg value="20" type="int" index="2"></constructor-arg>
    </bean>

4. Assigning values to bean s through namespaces simplifies the writing of attribute declarations in configuration files

  • p import namespace, c namespace, simpler naming, that's all
    1. Import namespace -- xml can be used after some specifications are brought in
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

2. Add configuration IOC xml

  <bean id="person6" class="com.mashibing.bean.Person" p:id="3" p:name="wangwu" p:age="22" p:gender="male"></bean>

5. Assign values to complex types (emphasis)

Summary:

  • Assign values to various complex types, such as sets, arrays, other objects, etc.
    Create the following class: person java , Book.java, Address.java as a demonstration

Person.java

import java.util.*;

public class Person {
    private int id;
    private String name="dahuang";
    private int age;
    private String gender;
    private Address address;
    private String[] hobbies;
    private List<Book> books;
    private Set<Integer> sets;
    private Map<String,Object> maps;
    private Properties properties; // This data type has never been used

    public Person(int id, String name, int age, String gender) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        System.out.println("Parametric constructor");
    }

    public Person(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
        System.out.println("Age");
    }

    public Person(int id, String name, String gender) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        System.out.println("gender");
    }

    public Person() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }

    public Set<Integer> getSets() {
        return sets;
    }

    public void setSets(Set<Integer> sets) {
        this.sets = sets;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", address=" + address +
                ", hobbies=" + Arrays.toString(hobbies) +
                ", books=" + books +
                ", sets=" + sets +
                ", maps=" + maps +
                ", properties=" + properties +
                '}';
    }
}

Book.java

public class Book {
    private String name;
    private String author;
    private double price;

    public Book() {
    }

    public Book(String name, String author, double price) {
        this.name = name;
        this.author = author;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }
}

Address.java

public class Address {
    private String province;
    private String city;
    private String town;

    public Address() {
    }

    public Address(String province, String city, String town) {
        this.province = province;
        this.city = city;
        this.town = town;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getTown() {
        return town;
    }

    public void setTown(String town) {
        this.town = town;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", town='" + town + '\'' +
                '}';
    }
}

ioc.xml

Assignments to complex types are property In label

        1. Assign as null
            <property name="name">
                <null></null>
            </property>
        2.External reference ref
        3.Reference internal bean
        4.by list assignment
        5.by set assignment
            <property name="sets">
                <set>
                    <value>111</value>
                    <value>222</value>
                    <value>222</value>
                </set>
            </property>
        6. by map assignment
            <property name="maps" ref="myMap"></property>
            <util:map id="myMap">
                <entry key="key1" value="value1"></entry>
                <entry key="key2" value-ref="book2"></entry>
                <entry key="key03">
                    <bean class="com.yao.bean.Book">
                        <property name="name" value="Journey to the West" ></property>
                        <property name="author" value="Wu Chengen" ></property>
                        <property name="price" value="100" ></property>
                    </bean>
                </entry>
            </util:map>
         7. Assign a value to an array
            <property name="hobbies">
                <array>
                    <value>book</value>
                    <value>movie</value>
                    <value>game</value>
                </array>
            </property>

ioc.xml

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

    <!--Assignments to complex types are property In label-->
    <bean id="person" class="com.mashibing.bean.Person">
        <property name="name">
            <!--Null value-->
            <null></null>
        </property>
        <!--adopt ref Reference other objects, reference external bean-->
        <property name="address" ref="address"></property>
        <!--Reference internal bean-->
       <!-- <property name="address">
            <bean class="com.mashibing.bean.Address">
                <property name="province" value="Beijing"></property>
                <property name="city" value="Beijing"></property>
                <property name="town" value="Xicheng District"></property>
            </bean>
        </property>-->
        <!--by list assignment-->
        <property name="books">
            <list>
                <!--inside bean-->
                <bean id="book1" class="com.mashibing.bean.Book">
                    <property name="name" value="Multithreading and high concurrency"></property>
                    <property name="author" value="hibernate "></property>
                    <property name="price" value="1000"></property>
                </bean>
                <!--external bean-->
                <ref bean="book2"></ref>
            </list>
        </property>
        <!--to map assignment-->
        <property name="maps" ref="myMap"></property>
        <!--to property assignment-->
        <property name="properties">
            <props>
                <prop key="aaa">aaa</prop>
                <prop key="bbb">222</prop>
            </props>
        </property>
        <!--Assign a value to an array-->
        <property name="hobbies">
            <array>
                <value>book</value>
                <value>movie</value>
                <value>game</value>
            </array>
        </property>
        <!--to set assignment-->
        <property name="sets">
            <set>
                <value>111</value>
                <value>222</value>
                <value>222</value>
            </set>
        </property>
    </bean>
    <bean id="address" class="com.mashibing.bean.Address">
        <property name="province" value="Hebei"></property>
        <property name="city" value="Handan"></property>
        <property name="town" value="Wu'an"></property>
    </bean>
    <bean id="book2" class="com.mashibing.bean.Book">
        <property name="name" value="JVM"></property>
        <property name="author" value="hibernate "></property>
        <property name="price" value="1200"></property>
    </bean>
    <!--Cascade attribute-->
    <bean id="person2" class="com.mashibing.bean.Person">
        <property name="address" ref="address"></property>
        <property name="address.province" value="Beijing"></property>
    </bean>
    <!--util Namespace to create a collection type bean-->
    <util:map id="myMap">
            <entry key="key1" value="value1"></entry>
            <entry key="key2" value-ref="book2"></entry>
            <entry key="key03">
                <bean class="com.mashibing.bean.Book">
                    <property name="name" value="Journey to the West" ></property>
                    <property name="author" value="Wu Chengen" ></property>
                    <property name="price" value="100" ></property>
                </bean>
            </entry>
    </util:map>
</beans>

6. Configuration of inheritance bean (temporarily unavailable)

This means that bean s can inherit
parent: specifies which bean the configuration information of the bean inherits from
parson2 inherits parson and modifies name
Abstract: Abstract bean s, with values in them, still exist but cannot be instantiated. abstract="true"
Demonstrate it yourself. It doesn't seem to be of any use.
ioc.xml

    <bean id="person" class="com.mashibing.bean.Person">
        <property name="id" value="1"></property>
        <property name="name" value="zhangsan"></property>
        <property name="age" value="21"></property>
        <property name="gender" value="male"></property>
    </bean>
    <!--parent:appoint bean Which configuration information is inherited from bean-->
    <bean id="person2" class="com.mashibing.bean.Person" parent="person">
        <property name="name" value="lisi"></property>
    </bean>

7. Dependency created by bean object (temporarily unavailable)

bean objects are created according to the order of beans in the configuration file. You can also use the dependent on tag to determine the order

    <bean id="book" class="com.mashibing.bean.Book" depends-on="person,address"></bean>
    <bean id="address" class="com.mashibing.bean.Address"></bean>
    <bean id="person" class="com.mashibing.bean.Person"></bean>

8. Scope control of the bean, whether it is a singleton (generally two types)

Fine node difference: (fine node during interview)
prototype: the multi instance bean will not be created when the container is started, and the object will be created only when the object is obtained
singleton: the object is created before the container is started

  Four scopes
  singleton Single case(Default mode)
  prototype Multi case mode
  spring 4.x In version:
  	request: Each time a request is sent, there is a new object
  	session: Each send session has a new object
  	These two methods are hardly used.
  test singleton
  Person2 person2 = context.getBean("person2",Person.class);
  Person3 person3 = context.getBean("person3",Person.class);
  System.out.println(Person2== person3); // ture;

ioc.xml

    <!--
    bean Scope of: singleton,prototype,request,session
    Singleton by default
    prototype: Multi instance
        Multiple instances will not be created when the container starts bean,The object is created only when it is acquired
        Each creation is a new object
    singleton: Default singleton
        The object is created before the container is started
        All objects obtained are the same
    -->
    <bean id="person4" class="com.mashibing.bean.Person" scope="prototype"></bean>

9. Create bean objects using factory pattern

What is the difference between a static factory and an instance factory?
Static factory: the factory itself does not need to create objects, but can be called through static methods. Object = factory class Static factory method name ();
Instance factory: the factory itself needs to create an object. Factory class factory object = new factory class; Factory object get object name ();
Advantages and disadvantages:
Instance factories are easier to expand.
PersonStaticFactory.java

  public class PersonStaticFactory { // Static factory class

      public static Person getPerson(String name){
          Person person = new Person();
          person.setId(1);
          person.setName(name);
          return person;
      }
  }

ioc.xml

<!--
Use of static plants:
class:Specify static factory class
factory-method:Specifies which method is a factory method
-->
  <bean id="person5" class="com.mashibing.factory.PersonStaticFactory" factory-method="getPerson">
        <!--constructor-arg: You can specify parameters for the method-->
        <constructor-arg value="lisi"></constructor-arg>
    </bean>

Test.java

  Factory creation: no need to use this PersonStaticFactory Class because it was created using the factory method of.
  Person2 person2 = context.getBean("person2",Person.class);
  System.out.println(Person2);

PersonInstanceFactory.java

  public class PersonInstanceFactory { // Instance factory class does not add static!!
    public Person getPerson(String name){
        Person person = new Person();
        person.setId(1);
        person.setName(name);
        return person;
    }
  }

ioc.xml

    <!--Instance factory usage-->
    <!--Create instance factory class-->
    <bean id="personInstanceFactory" class="com.mashibing.factory.PersonInstanceFactory"></bean>
    <!--
    factory-bean:Specify which factory instance to use
    factory-method:Specifies the method of which factory instance to use
    -->
    <bean id="person6" class="com.mashibing.bean.Person" factory-bean="personInstanceFactory" factory-method="getPerson">
        <constructor-arg value="wangwu"></constructor-arg>
    </bean>

10. Inherit FactoryBean to create objects (generally not used, but seen in the source code)

  BeanFactory Interface, specification
  FactoryBean: Gets a unique object.
  	Self created objects can also be handed over to spring Administration.
  	It means that I can give what I created to you Spring Management uses the following>
  use:
  	1)realization FactoryBean<What kind of object is here person>Interface
  	2)Three methods:
  		Factory method to return the object to be created
  		Returns the type of the object
  		No is a singleton object
  	3)hand spring  to configure ioc.xml There are below
  Summary:
  	It is a supplement to creating objects. It is created only when it is used. It is not created when it is not used. There is no relationship between single case and multiple cases
  You don't have to. The source code will be used more.

11. Initialization and destruction methods of bean objects (understand)

Initialization differs from single instance and multiple instances:(Generally no one uses it. I don't know during the interview)
    If bean This is a single example. The container will be created when it is started and destroyed when it is closed bean
    If bean There are multiple instances. Objects are created when they are acquired, and there will be no calls when they are destroyed

12. Configure the pre-processing and post-processing methods of bean object initialization method (understand)

POSTxxxx Interface

3. spring creates a third-party bean object (configure database connection pool)

1. Import pom file of database connection pool

  <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.21</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
  </dependency>

2. Write configuration file

  <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
  <!--
  Spring Managing third parties Bean object
  -->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="username" value="root"></property>
          <property name="password" value="123456"></property>
          <property name="url" value="jdbc:mysql://localhost:3306/demo"></property>
          <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
      </bean>
  </beans>

3. Write test documents

  public class MyTest {
      public static void main(String[] args) throws SQLException {
          ApplicationContext context = new ClassPathXmlApplicationContext("ioc3.xml");
          DruidDataSource dataSource = context.getBean("dataSource", DruidDataSource.class);
          System.out.println(dataSource);
          System.out.println(dataSource.getConnection());
      }
  }

4. spring references an external configuration file

5. spring automatic assembly based on xml file

  In front address This class, in ioc.xml Yes, it is propotery Assembly.
  Now auto assemble:
  How?
  byName:according to set Method. The first caption must be lowercase.
  Type: Assemble according to the type. If there are multiple same types, an error will be reported.

When an object needs to reference another object, we manually configured it through the property tag in the previous configuration. In fact, spring also provides a very powerful function of automatic assembly, which can be configured according to the rules specified by us. The configuration methods are as follows:

default/no: do not auto assemble

byName: assemble according to the name, use the attribute name as the id to find the component in the container and assign a value. If it cannot be found, the assembly will be null

byType: assemble according to the type. Find this component in the container based on the type of the attribute. If there are multiple bean objects of the same type, an exception will be reported. If not found, null will be assembled

Constructor: assemble according to the constructor. First, assemble according to the type of constructor parameters with parameters. If not, directly assemble null; If more than one is found according to the type, the parameter name will be used as the id to continue matching. If it is found, it will be assembled, and if it is not found, it will be assembled null

6. Use of spiel (simple syntax sugar, easy to write bean s)

You can only see it when the company asks you to use it. It's useless to see it now.

7. Annotation application of spring IOC

Annotation ID in Spring:

Spring There are 4 main components to add notes:
 @Controller:Controller, recommended for controller Add this annotation to the layer(Accept user requests web Used to)
 @Service:Business logic. It is recommended to add this annotation to the business logic layer
 @Repository:For warehouse management, it is recommended to add this annotation to the data access layer
 @Component:To those who do not belong to the above grass-roots level**assembly**Add this annotation(If you don't understand anything, just add this)

Annotation usage steps

Using annotations requires the following steps:
 1,Add any of the above four annotations
 2,Add a component that automatically scans annotations. This operation requires dependencies context Namespace
 3,Add automatically scanned labels context:component-scan(All classes under the current package are scanned)

Question: when using annotations, we don't define id and class. How can he identify them?

The default class name is lowercase, but can be aliased. Generally, no one does so. Add value = "xxxxxx" in the annotation identification bracket, such as @ controller (value = "class name can be changed");

Scanning packets can be used for fine-grained segmentation (useless)

Use @ AutoWired for automatic injection (difficult to understand, see the video)

Interview questions:

  Note: when using AutoWired Annotation and automatic assembly are implemented according to type.
  1,If only one is found, assign the value directly,
  2,If it is not found, an exception is thrown directly,
  3,If more than one is found, the variable name is used as the id Continue matching,
    1,Direct assembly on matching
    2,If there is no match, an exception will be reported directly

You can also use@Qualifier Annotation to specify id Name, let spring Do not use variable names,When used@Qualifier There are also two situations when commenting:
  1,If found, assemble directly
​  2,If it cannot be found, an error will be reported

@AutoWired can be defined in methods

Annotation for auto assembly @ AutoWired, @ Resource

Interview questions:

When using automatic assembly, it can be used when it is out@AutoWired In addition to annotations, you can also use@Resource Note, you need to know this**Difference between two annotations**. 
​		1,@AutoWired:yes spring Notes provided in,@Resource:yes jdk The annotation defined in depends on java Standard of
​		2,@AutoWired The default is to assemble by type. By default, dependent objects must exist,@Resource The default is to match by name, and you can specify name Properties.
​		3,@AutoWired Only suitable spring Frame, and@Resource Better scalability

6. Generic dependency injection (skip first)

Keywords: Spring

Added by mulysa on Sun, 23 Jan 2022 17:27:17 +0200