[java framework] Spring -- Spring Dependent Injection Configuration

1. Spring Dependent Injection Method

Today, I'm going to focus on the various injection-dependent ways in the Spring framework and the associated set of configurations, which are the core fascination of Spring's lightweight DI, IOC Bean container framework.

Spring Dependent Injection This article highlights the constructor parameter injection, multi-type (Arrays, Set, List, Map, Properties object) injection, XML auto-injection, and full annotation configuration injection.

The following are explanations of these different injection methods:

1.1. Constructor parameter injection

In Getting Started with Spring(1), we learned that after configuring beans in the ApplicationContext.xml file, using SpringTest to get Bean objects must ensure that there are parameterized construction methods in the class in which the beans reside, or the following errors will occur:

After configuring the parametric construction method, the corresponding properties in the obtained Bean are also null, as shown in the following figure:

That doesn't require a parameterless construct and how do I configure the attribute values I want to inject into the Bean?

Constructor parameter injection solves the above problem. There are three configurations for constructor parameter injection, as follows:

(1) Injection according to constructor parameter index;

<bean id="myBean" class="cn.yif.demo1_constructor.MyBean">
<!--Mode 1: Inject index according to the index of the constructor parameter: start from 0, property location; value: set value-->
<constructor-arg index="0" value="Lina"></constructor-arg>
<constructor-arg index="1" value="21"></constructor-arg>
</bean>

(2) Inject according to the name of the constructor parameter;

<bean id="myBean" class="cn.yif.demo1_constructor.MyBean">
<!--Mode 2: Inject name: attribute name; value: set value-->
<constructor-arg name="username" value="Lina"></constructor-arg>
<constructor-arg name="age" value="21"></constructor-arg>
</bean>

(3) Injection according to the type of constructor;

<bean id="myBean" class="cn.yif.demo1_constructor.MyBean">
<!--Mode 3: Inject according to the type of constructor  type: Fully qualified name of type; value: Set Value-->
<constructor-arg type="java.lang.String" value="Lina"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="21"></constructor-arg>
</bean>

(4) Special cases: If one property is an object of another class (Bean), there are two ways to inject it;

Mode 1: Externally defined, internal constructors are introduced using ref;

<bean id="otherBean" class="cn.yif.demo1_constructor.OtherBean">
 <property name="otherAge" value="24"></property>
 <property name="otherName" value="Li Yong"></property>
</bean>
<!--Mode 1: otherBean Defined externally, internally constructor-arg Use ref Introduce-->
<bean id="myBean" class="cn.yif.demo1_constructor.MyBean">
 <constructor-arg index="0" value="Lina"></constructor-arg>
 <constructor-arg index="1" value="21"></constructor-arg>
 <constructor-arg ref="otherBean"></constructor-arg>
</bean>

 

Mode 2: Use a complete bean to inject in the internal constructor-arg tag

<!--Mode 2: In constructor-arg Internal use bean Label defines a Bean-->
<bean id="myBean" class="cn.yif.demo1_constructor.MyBean">
   <constructor-arg value="Lina"></constructor-arg>
   <constructor-arg value="21"></constructor-arg>
   <constructor-arg>
        <bean id="otherBean" class="cn.yif.demo1_constructor.OtherBean">
             <property name="otherAge" value="24"></property>
             <property name="otherName" value="Li Yong"></property>
        </bean>
   </constructor-arg>
</bean>

1.2. Multi-type (Arrays, Set, List, Map, Properties object) injection

Prepare a MultiTypeBean class with multiple types of attributes and provide setter and toString methods.

import cn.yif.demo1_constructor.OtherBean;
import java.math.BigDecimal;
import java.util.*;
public class MultiTypeBean {
// Simple Attributes
private Long id;
private String name;
private Boolean sex;
private BigDecimal salary;

// Object Properties
private List<String> list;
private List<OtherBean> otherBeanList;
private Set<String> set;
private Set<OtherBean> otherBeanSet;
private Map<String,Object> map;

//Properties Resource attributes and String Array Properties
private Properties props1;
private Properties props2;
private String[] arrays;

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

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

public void setSex(Boolean sex) {
    this.sex = sex;
}

public void setSalary(BigDecimal salary) {
    this.salary = salary;
}

public void setList(List<String> list) {
    this.list = list;
}

public void setOtherBeanList(List<OtherBean> otherBeanList) {
    this.otherBeanList = otherBeanList;
}

public void setSet(Set<String> set) {
    this.set = set;
}

public void setOtherBeanSet(Set<OtherBean> otherBeanSet) {
    this.otherBeanSet = otherBeanSet;
}

public void setMap(Map<String, Object> map) {
    this.map = map;
}
public void setProps1(Properties props1) {
    this.props1 = props1;
}

public void setProps2(Properties props2) {
    this.props2 = props2;
}

public void setArrays(String[] arrays) {
    this.arrays = arrays;
}

@Override
public String toString() {
    return "MultiTypeBean{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", sex=" + sex +
            ", salary=" + salary +
            ", list=" + list +
            ", otherBeanList=" + otherBeanList +
            ", set=" + set +
            ", otherBeanSet=" + otherBeanSet +
            ", map=" + map +
            ", props1=" + props1 +
            ", props2=" + props2 +
            ", arrays=" + Arrays.toString(arrays) +
            '}';
}
}

1.2.1. * Arrays array injection

Write 1. Short form:

<property name="arrays" value="xxx,yyy,zzz"></property>

Writing 2, Formal Writing:

<property name="arrays">
  <array>
      <value>xxx</value>
      <value>yyy</value>
      <value>zzz</value>
  </array>
</property>

1.2.2. * List Collection Injection

<!—about List<String>Injection-->
<property name="list">
 <list>
     <value>aaa</value>
     <value>bbb</value>
     <value>ccc</value>
  </list>
</property>
<!—about List<OtherBean>Injection-->
<property name="otherBeanList">
 <list>
         <bean id="otherBean" class="cn.yif.demo1_constructor.OtherBean"></bean>
 </list>
</property>

1.2.3. * Set Collection Injection

<!—about Set<String>Injection-->
<property name="set">
  <set>
      <value>aaa</value>
      <value>bbb</value>
      <value>ccc</value>
  </set>
</property>
<!—about Set<OtherBean>Injection-->
<property name="otherBeanSet">
  <set>
      <bean id="otherBean" class="cn.yif.demo1_constructor.OtherBean"></bean>
      <bean id="otherBean" class="cn.yif.demo1_constructor.OtherBean"></bean>
  </set>
</property>

1.2.4. * Map Dictionary Injection

<property name="map">
  <map>
      <entry key="username" value="Li Li"></entry>
      <entry key="age" value="21"></entry>
  </map>
</property>

1.2.5. * Properties Resource Property Injection

<property name="props1">
  <value>
      Jpa.dialect=org.Jpa.dialect.HSQLDialect
      Jpa.driverClassName=com.mysql.jdbc.Driver
  </value>
</property>
<property name="props2">
  <props>
      <prop key="Jpa.dialect">org.Jpa.dialect.HSQLDialect</prop>
      <prop key="Jpa.driverClassName">com.mysql.jdbc.Driver  Support Chinese</prop>
</props>
</property>

1.2.6. * General Field Attribute Injection

<property name="id" value="1"></property>
<property name="name" value="Li Hua"></property>
<property name="sex" value="true"></property>
<property name="salary" value="8045.5"></property>

1.3. Automatic XML Injection

There are two ways to inject configurations using XML injection beans:

(1) byType method

This is done by injecting according to the type of injected object. Note that a type requires only one instance to be configured. A type represents a corresponding entity implementation class, such as interface IUserDao. There cannot be two implementation class types in the configuration file, otherwise the following exception will be thrown:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [cn.yif.demo3_xmlautoinject.IUserDao] is defined: expected single matching bean but found 2: jdbcDao,jpaDao

(2) byName mode

This is done by injecting the name of the bean, which is the value of the id in the bean configuration

3. Scope of use of configuration

Root node beans default-autowire="byName" is valid for all beans in the current profile

Child node bean autowire="byType" is valid only for the current bean

Examples of configurations are as follows:

<?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" default-autowire="byType">
    <!--default-autowire="byType": Represents a global injection method, all bean adopt byType Mode Injection-->
    <bean id="jdbcDao" class="cn.yif.demo3_xmlautoinject.UserJDBCDaoImpl"></bean>
    <!--<bean id="jpaDao" class="cn.yif.demo3_xmlautoinject.UserJPADaoImpl" autowire="byName"></bean>-->
    <!--userService Need userDao This type, I pass byType Just inject this type into you-->
    <!--autowire="byName"Represent this bean The way I inject is customized by me, and I use byName Mode Injection-->
    <bean id="userService" class="cn.yif.demo3_xmlautoinject.UserServiceImpl" autowire="byName">
    </bean>
    <!--userAction Need userService This implements the properties of the class that I use byType Just inject this type into you-->
   <bean id="userAction" class="cn.yif.demo3_xmlautoinject.UserAction">
   </bean>
</beans>

1.4. Full Note Configuration

1.4.1. Full Note Configuration Usage

Writing XML to configure beans in Java is cumbersome, and Spring provides a fully annotated way to configure beans for simplicity.Here are the steps to configure beans using full annotations:

(1) Configure the context namespace in the ApplicationContext.xml or SpringXXXTest-Context.xml file of the current package path to tell Spirng which package directory to scan for annotations;

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- Scan packages,See if there is a corresponding label configuration on the class -->
<context:component-scan base-package="cn.yif.demo4_allannotations" />
<!-- This is not required(spring3.2 Use before version) Good compatibility after pairing -->
<context:annotation-config />
</beans>

(2) Spring provides four annotation types: @Component, @Repository, @Service, @Controller for annotations, indicating that this class needs to be managed as a Bean by Spring.

Typically @Component represents a component and is used when you do not know which layer it is in a three-tier structure;

@Repository is typically used for the Dao data persistence layer;

@Service is typically used for business-tier annotations;

@Controller is typically used for the presentation layer (control layer).

The configuration is as follows:

Action layer:

@Controller
public class UserAction {
   @Autowired
   private IUserService userService;

   public void insert(){
       System.out.println("UserAction insert...");
       userService.insert();
   }

}

Service layer:

@Service
public class UserServiceImpl implements IUserService {
   @Autowired
   private IUserDao userJPADaoImpl;
   public void insert(){
       System.out.println("UserService insert...");
       userJPADaoImpl.insert();
   }
}

Dao Layer:

@Repository
public class UserJDBCDaoImpl implements IUserDao {
   @Override
   public void insert() {
       System.out.println("UserJDBCDao insert...");
   }
}

1.4.2. Full Note Configuration Details

There is a hidden problem with the full annotation configuration here, such as I have a Dao interface as is, but there are two implementations of IUserDao_UserJDBCDaoImpl/UserJPADaoImpl for this interface, and the following errors will occur during injection:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [cn.yif.demo4_allannotations.IUserDao] is defined: expected single matching bean but found 2: userJDBCDaoImpl,userJPADaoImpl

There are two solutions:

First add a name to the beans generated by Dao, and we can call them by name when we call them.

@Repository("userJDBCDao")
public class UserJDBCDaoImpl implements IUserDao {
@Override
public void insert() {
    System.out.println("UserJDBCDao insert...");
}
}

@Repository("userJPADao")
public class UserJPADaoImpl implements IUserDao {
   @Override
   public void insert() {
       System.out.println("UserJPADao insert...");
   }
}

When invoking, we can invoke the Bean annotation under the corresponding name using the annotation provided by Spring or Sun as follows:

(1) Use a set of comments @Qualifier("Configured Bean Name") provided by Spring Inc.

@Service
public class UserServiceImpl implements IUserService {
   @Autowired
   @Qualifier("userJPADao")
   private IUserDao userDao;
   public void insert(){
       System.out.println("UserService insert...");
       userDao.insert();
   }
}

(2) Bean name configured with @Resource(name=")

@Service
public class UserServiceImpl implements IUserService {
@Resource(name = "userJDBCDao")
private IUserDao userDao;
public void insert(){
    System.out.println("UserService insert...");
    userDao.insert();
}
}

Summary: Full annotation configuration is now generally used, which is simpler and more flexible.

Tags: Java Spring xml Attribute

Posted on Tue, 10 Mar 2020 09:42:59 -0700 by SerpentSword