【Spring】Injection topic

Based on the latest Spring framework tutorial of [Power Node], the first Spring 6 tutorial on the entire network, learn spring from scratch to advanced with Lao Du and Lao Du’s original notes https://www.yuque.com/docs/share/866abad4-7106 -45e7-afcd-245a733b073f?# "Spring6" is organized, document password: mg9b


Spring related articles are compiled and summarized at: https://www.yuque.com/u27599042/zuisie


set injection topic

Inject external beans

  • External Bean: The bean to be injected is defined outside the bean that needs to be injected.
  • For external beans, use the ref attribute in the property tag for injection, or use the ref tag for injection. Injection through the ref attribute is commonly used.
<!--声明/定义Bean-->
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"></bean>

<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
    <!--使用ref属性来引入外部Bean,这就是注入外部Bean-->
    <property name="orderDao" ref="orderDaoBean"/>
</bean>

Inject internal beans

  • Internal Bean: Nest the bean tag in the bean tag, that is, the bean that needs to be injected is declared in the bean that needs to be injected through the bean tag, and then directly injected into the bean that needs to be injected.
<bean id="orderServiceBean2" class="com.powernode.spring6.service.OrderService">
    <property name="orderDao">
        <!--在property标签中使用嵌套的bean标签,这就是内部Bean-->
        <bean class="com.powernode.spring6.dao.OrderDao"></bean>
    </property>
</bean>

Inject simple types

  • If you assign a value to a simple type, that is, inject a simple type into an attribute, use the value attribute or value tag instead of ref.
public class User {
    
    
    private String username; // String是简单类型
    private String password;
    private int age; // int是简单类型

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

    public void setPassword(String password) {
    
    
        this.password = password;
    }

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

    @Override
    public String toString() {
    
    
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}
<!--注入简单类型-->
<bean id="userBean" class="com.powernode.spring6.bean.User">
    <!--重点:如果是给简单类型赋值,就不能使用ref了。就需要使用value了。-->
    <property name="username" value="张三"/>
    <property name="password" value="123"/>
    <property name="age" value="20"/>
</bean>

Simple types in Spring

  • Through source code analysis of the BeanUtils class, we know that simple types include:
    • Basic data types
    • Packaging class corresponding to basic data type
    • String or other CharSequence subclass
    • Number subclass
    • Date subclass, java.util.Date is a simple type
    • Enum subclass
    • URI
    • URL
    • Temporal subclass, Temporal is the time and time zone type provided by Java8
    • Locale, Locale is a language class and a simple type.
    • Class
    • It also includes array types corresponding to the above simple value types.
public class BeanUtils{
    
    
    
    //.......
    
    /**
	 * Check if the given type represents a "simple" property: a simple value
	 * type or an array of simple value types.
	 * <p>See {@link #isSimpleValueType(Class)} for the definition of <em>simple
	 * value type</em>.
	 * <p>Used to determine properties to check for a "simple" dependency-check.
	 * @param type the type to check
	 * @return whether the given type represents a "simple" property
	 * @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE
	 * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies
	 * @see #isSimpleValueType(Class)
	 */
	public static boolean isSimpleProperty(Class<?> type) {
    
    
		Assert.notNull(type, "'type' must not be null");
		return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
	}

	/**
	 * Check if the given type represents a "simple" value type: a primitive or
	 * primitive wrapper, an enum, a String or other CharSequence, a Number, a
	 * Date, a Temporal, a URI, a URL, a Locale, or a Class.
	 * <p>{@code Void} and {@code void} are not considered simple value types.
	 * @param type the type to check
	 * @return whether the given type represents a "simple" value type
	 * @see #isSimpleProperty(Class)
	 */
	public static boolean isSimpleValueType(Class<?> type) {
    
    
		return (Void.class != type && void.class != type &&
				(ClassUtils.isPrimitiveOrWrapper(type) ||
				Enum.class.isAssignableFrom(type) ||
				CharSequence.class.isAssignableFrom(type) ||
				Number.class.isAssignableFrom(type) ||
				Date.class.isAssignableFrom(type) ||
				Temporal.class.isAssignableFrom(type) ||
				URI.class == type ||
				URL.class == type ||
				Locale.class == type ||
				Class.class == type));
	}
    
    //........
}

Test all simple types

  • Write a program to test all simple types:
package com.powernode.spring6.beans;

import java.net.URI;
import java.net.URL;
import java.time.LocalDate;
import java.util.Date;
import java.util.Locale;

public class A {
    
    
    private byte b;
    private short s;
    private int i;
    private long l;
    private float f;
    private double d;
    private boolean flag;
    private char c;

    private Byte b1;
    private Short s1;
    private Integer i1;
    private Long l1;
    private Float f1;
    private Double d1;
    private Boolean flag1;
    private Character c1;

    private String str;

    private Date date;

    private Season season;

    private URI uri;

    private URL url;

    private LocalDate localDate;

    private Locale locale;

    private Class clazz;
    
    // 生成setter方法
    // 生成toString方法
}

enum Season {
    
    
    SPRING, SUMMER, AUTUMN, WINTER
}
  • have to be aware of is:
    • If Date is regarded as a simple type, the date string format cannot be written casually, and the format must conform to the format of Date's toString() method. Obviously this is rather tasteless. If we provide a date string like this: 2010-10-11, it cannot be assigned to an attribute of Date type here.
    • After spring6, when a URL is injected, the validity of the URL string will be checked. If it is an existing url, then no problem. If it does not exist, an error will be reported.

Classic case of injecting simple types

  • Classic case: injecting values ​​into attributes of the data source:
  • Suppose we want to hand-write a data source now. We all know that all data sources must implement the javax.sql.DataSource interface, and the data source should have information to connect to the database, such as: driver, url, username, password, etc.
  • Data source: All data sources can provide you with Connection objects.
/**
 * 所有的数据源都要实现java规范:javax.sql.DataSource
 **/
public class MyDataSource implements DataSource {
    
     // 可以把数据源交给Spring容器来管理。

    private String driver;
    private String url;
    private String username;
    private String password;

    public void setDriver(String driver) {
    
    
        this.driver = driver;
    }

    public void setUrl(String url) {
    
    
        this.url = url;
    }

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

    public void setPassword(String password) {
    
    
        this.password = password;
    }

    @Override
    public String toString() {
    
    
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    @Override
    public Connection getConnection() throws SQLException {
    
    
        // 获取数据库连接对象的时候需要4个信息:driver url username password
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
    
    
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
    
    
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
    
    

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
    
    

    }

    @Override
    public int getLoginTimeout() throws SQLException {
    
    
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
    
    
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
    
    
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
    
    
        return false;
    }
}
<!--让spring来管理我们的数据源-->
<bean id="myDataSource" class="com.powernode.spring6.jdbc.MyDataSource">
    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/spring6"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>
@Test
public void testDataSource(){
    
    
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-datasource.xml");
    MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class);
    System.out.println(dataSource);
}

cascading property assignments

// 班级类
public class Clazz {
    
    
    // 班级名称
    private String name;

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

    @Override
    public String toString() {
    
    
        return "Clazz{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class Student {
    
    
    private String name;

    // 学生属于哪个班级
    private Clazz clazz;

    public void setClazz(Clazz clazz) {
    
    
        this.clazz = clazz;
    }

    // 使用级联属性赋值,这个需要这个get方法。
    // 因为级联给学生所在的班级属性赋值会调用学生的getClazz()方法
    public Clazz getClazz() {
    
    
        return clazz;
    }

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

    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                ", clazz=" + clazz +
                '}';
    }
}
  • Original injection method
<bean id="studentBean" class="com.powernode.spring6.bean.Student">
    <!--简单类型,使用value-->
    <property name="name" value="张三"/>
    <!--这不是简单类型,使用ref-->
    <property name="clazz" ref="clazzBean"/>
</bean>

<bean id="clazzBean" class="com.powernode.spring6.bean.Clazz">
    <property name="name" value="高三一班"/>
</bean>
  • Cascade injection:
  • Note: For cascading attribute assignment, the get method must be provided for member variables that reference other objects, because when performing cascading attribute assignment, you need to first call the get method to obtain the member variables that reference other objects, and then call the member variable. Attribute set method for attribute assignment
<!--使用级联属性赋值需要注意两点:
        1. 配置的顺序不能颠倒,必须如下顺序。
        2. clazz属性必须提供getter方法。
-->
<bean id="studentBean" class="com.powernode.spring6.bean.Student">
    <!--简单类型,使用value-->
    <property name="name" value="张三"/>
    <!--这不是简单类型,使用ref-->
		<!-- 因为后面要对该对象的属性赋值,所以必须先有该对象 -->
    <property name="clazz" ref="clazzBean"/>
    <!--级联属性赋值-->
    <!-- name="clazz.name" 会调用学生的getClazz()方法,
  			所以学生类必须提供getClazz()方法,然后调用set方法给班级的name赋值 
  	-->
    <property name="clazz.name" value="高三二班"/>
</bean>

<!-- 这里不进行注入 -->
<bean id="clazzBean" class="com.powernode.spring6.bean.Clazz"></bean>

inject array

The elements in the array are simple types

public class QianDaYe {
    
    
    private String[] aiHaos;

    public void setAiHaos(String[] aiHaos) {
    
    
        this.aiHaos = aiHaos;
    }

    @Override
    public String toString() {
    
    
        return "QianDaYe{" +
                "aiHaos=" + Arrays.toString(aiHaos) +
                '}';
    }
}
<bean id="yuQian" class="com.powernode.spring6.bean.QianDaYe">

    <!-- 这个数组属性当中的元素类型是String,是简单类型 -->
    <property name="aiHaos">
        <array>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </array>
    </property>

</bean>

The elements in the array are of non-simple type

public class Woman {
    
    
    private String name;

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

    @Override
    public String toString() {
    
    
        return "Woman{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class QianDaYe {
    
    
    private String[] aiHaos;

    // 多个女性朋友
    private Woman[] womens;

    public void setWomens(Woman[] womens) {
    
    
        this.womens = womens;
    }

    public void setAiHaos(String[] aiHaos) {
    
    
        this.aiHaos = aiHaos;
    }

    @Override
    public String toString() {
    
    
        return "QianDaYe{" +
                "aiHaos=" + Arrays.toString(aiHaos) +
                ", womens=" + Arrays.toString(womens) +
                '}';
    }
}
<bean id="w1" class="com.powernode.spring6.bean.Woman">
    <property name="name" value="小花"/>
</bean>

<bean id="w2" class="com.powernode.spring6.bean.Woman">
    <property name="name" value="小亮"/>
</bean>

<bean id="w3" class="com.powernode.spring6.bean.Woman">
    <property name="name" value="小明"/>
</bean>

<bean id="yuQian" class="com.powernode.spring6.bean.QianDaYe">

    <!-- 这个数组属性当中的元素类型是String简单类型 -->
    <property name="aiHaos">
        <array>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </array>
    </property>

    <!-- 这个数组当中的类型就不是简单类型了-->
    <property name="womens">
        <array>
            <ref bean="w1"/>
            <ref bean="w2"/>
            <ref bean="w3"/>
        </array>
    </property>

</bean>

Injection array summary

  • If the array contains simple types, use the value tag.
  • If the array contains non-simple types, use the ref tag.

Inject List collection and Set collection

  • List collection: ordered and repeatable
    • Note: Use the list tag when injecting the List collection, if the List collection is a simple type, use the value tag, otherwise use the ref tag.
  • Set collection: unordered and non-repeatable
    • Key points: Use tags when injecting the set collection <set>, if the elements in the set collection are simple types, use the value tag, otherwise use the ref tag.
public class Person {
    
    

    // 注入List集合
    private List<String> names;

    // 注入Set集合
    private Set<String> addrs;

    public void setNames(List<String> names) {
    
    
        this.names = names;
    }

    public void setAddrs(Set<String> addrs) {
    
    
        this.addrs = addrs;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "names=" + names +
                ", addrs=" + addrs +
                '}';
    }
}
<bean id="personBean" class="com.powernode.spring6.bean.Person">

    <property name="names">
        <!--list集合有序可重复-->
        <list>
            <value>张三</value>
            <value>李四</value>
            <value>王五</value>
            <value>张三</value>
            <value>张三</value>
            <value>张三</value>
            <value>张三</value>
        </list>
    </property>

    <property name="addrs">
        <!--set集合无序不可重复-->
        <set>
            <value>北京大兴区</value>
            <value>北京大兴区</value>
            <value>北京海淀区</value>
            <value>北京海淀区</value>
            <value>北京大兴区</value>
        </set>
    </property>
</bean>

Inject Map collection and inject Properties

  • Map collection:
    • use <map>tags
    • If the key is a simple type, use the key attribute, otherwise use the key-ref attribute.
    • If the value is a simple type, use the value attribute, otherwise use the value-ref attribute.
  • java.util.Properties inherits java.util.Hashtable, so Properties is also a Map collection.
    • Properties are done using <props>tags nested within <prop>tags.
    • In Properties, the key and value types are both String types.
public class Person {
    
    

    // 注入Map集合
    // 多个电话
    private Map<Integer, String> phones;

    // 注入属性类对象
    // Properties本质上也是一个Map集合。
    // Properties的父类Hashtable,Hashtable实现了Map接口。
    // 虽然这个也是一个Map集合,但是和Map的注入方式有点像,但是不同。
    // Properties的key和value只能是String类型。
    private Properties properties;

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

    public void setPhones(Map<Integer, String> phones) {
    
    
        this.phones = phones;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "phones=" + phones +
                ", properties=" + properties +
                '}';
    }
}
<bean id="personBean" class="com.powernode.spring6.bean.Person">
    
    <property name="properties">
        <!--注入Properties属性类对象-->
        <props>
            <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
            <prop key="url">jdbc:mysql://localhost:3306/spring6</prop>
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
        </props>
    </property>

    <property name="phones">
        <!--注入Map集合-->
        <map>
            <!--如果key和value不是简单类型就用这个配置。-->
            <!--<entry key-ref="" value-ref=""/>-->
            <!--如果是简单类型就是key和value-->
            <entry key="1" value="110"/>
            <entry key="2" value="120"/>
            <entry key="3" value="119"/>
        </map>
    </property>
</bean>

Inject null and empty string

  • To inject an empty string use: <value/>or value=""
  • To inject null use: <null/>or do not assign a value to this property
public class Cat {
    
    
    private String name;
    private int age;

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

    public String getName() {
    
    
        return name;
    }

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

    @Override
    public String toString() {
    
    
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
<bean id="catBean" class="com.powernode.spring6.bean.Cat">
    <!--不给属性注入,属性的默认值就是null-->
    <!--<property name="name" value="tom"></property>-->
    <!-- 这不是注入null,这只是注入了一个"null"字符串-->
    <!--<property name="name" value="null"/>-->
    <!--这种方式是手动注入null-->
    <!--<property name="name">
        <null/>
    </property>-->

    <!--注入空字符串第一种方式-->
    <!--<property name="name" value=""/>-->
    <!--注入空字符串第二种方式-->
    <property name="name">
        <value/>
    </property>

    <property name="age" value="3"></property>
</bean>

The injected value contains special symbols

  • There are 5 special characters in XML, namely: <, >, ', ", &
  • The above five special symbols will be treated specially in XML and will be parsed as part of the XML syntax. If these special symbols appear directly in the injected string, an error will be reported.
  • Solutions include two types:
    • Type 1: Use escape characters to replace special symbols.
    • The second type: put the string containing special symbols into <![CDATA[]]>:. Data placed in the CDATA area will not be parsed by the XML file parser. When using CDATA, the value attribute cannot be used, only the value tag can be used.
  • The escape characters corresponding to the 5 special characters are:
public class MathBean {
    
    
    private String result;

    public void setResult(String result) {
    
    
        this.result = result;
    }

    @Override
    public String toString() {
    
    
        return "MathBean{" +
                "result='" + result + '\'' +
                '}';
    }
}
    <bean id="mathBean" class="com.powernode.spring6.bean.MathBean">
        <!--第一种方案:使用实体符号代替特殊符号-->
        <!--<property name="result" value="2 &lt; 3" />-->

        <!--第二种方案:使用<![CDATA[]]>-->
        <property name="result">
            <!--只能使用value标签-->
            <value><![CDATA[2 < 3]]></value>
        </property>

    </bean>

p namespace injection

  • Purpose: Simplify configuration.
  • The p namespace is actually a simplification of set injection.
  • The prerequisites for using p namespace injection include two:
    • First: Add the configuration information of the p namespace in the XML header information:xmlns:p="http://www.springframework.org/schema/p"
    • Second: p namespace injection is based on the setter method, so the corresponding attribute needs to provide a setter method.
public class Dog {
    
    
    // 简单类型
    private String name;
    private int age;
    // 非简单类型
    private Date birth;

    // p命名空间注入底层还是set注入,只不过p命名空间注入可以让spring配置变的更加简单。
    public void setName(String name) {
    
    
        this.name = name;
    }

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

    public void setBirth(Date birth) {
    
    
        this.birth = birth;
    }

    @Override
    public String toString() {
    
    
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birth=" + birth +
                '}';
    }
}
<?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">

    <!--
        第一步:在spring的配置文件头部添加p命名空间。
  					xmlns:p="http://www.springframework.org/schema/p"
        第二步:使用 p:属性名 = "属性值"
    -->
    <bean id="dogBean" class="com.powernode.spring6.bean.Dog" p:name="小花" p:age="3" p:birth-ref="birthBean"/>

    <!--这里获取的是当前系统时间。-->
    <bean id="birthBean" class="java.util.Date"/>

</beans>

c namespace injection

  • The c namespace simplifies constructor injection.
  • Two prerequisites for using the c namespace:
    • First: You need to add the c namespace configuration information to the header of the xml configuration file:xmlns:c="http://www.springframework.org/schema/c"
    • Second: Construction methods need to be provided.
  • The c namespace relies on constructors.
  • Note: Whether it is the p namespace or the c namespace, both simple types and non-simple types can be injected during injection.
public class People {
    
    
    private String name;
    private int age;
    private boolean sex;

    // c命名空间是简化构造注入的。
    // c命名空间注入办法是基于构造方法的。
    public People(String name, int age, boolean sex) {
    
    
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
    
    
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        第一步:在spring的配置文件头部添加: 
  					xmlns:c="http://www.springframework.org/schema/c"
        第二步:使用
            c:_0 下标方式
            c:name 参数名方式
    -->
    <!--<bean id="peopleBean" class="com.powernode.spring6.bean.People" c:_0="zhangsan" c:_1="30" c:_2="true"></bean>-->
    <bean id="peopleBean" class="com.powernode.spring6.bean.People" c:name="jack" c:age="30" c:sex="true"></bean>

</beans>

util namespace

  • Using the util namespace allows configuration reuse.
  • The prerequisite for using the util namespace is to add configuration information to the head of the spring configuration file.
  • 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"
  
       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 http://www.springframework.org/schema/util/spring-util.xsd">
package com.powernode.spring6.beans;

import java.util.Properties;

public class MyDataSource1 {
    
    
	// Properties属性类对象,这是一个Map集合,
    // key和value都是String类型。
    private Properties properties;

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

    @Override
    public String toString() {
    
    
        return "MyDataSource1{" +
                "properties=" + properties +
                '}';
    }
}
package com.powernode.spring6.beans;

import java.util.Properties;

public class MyDataSource2 {
    
    
    private Properties properties;

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

    @Override
    public String toString() {
    
    
        return "MyDataSource2{" +
                "properties=" + properties +
                '}';
    }
}
<?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: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 http://www.springframework.org/schema/util/spring-util.xsd">

    <!--引入util命名空间
        在spring的配置文件头部添加:
        		xmlns:util="http://www.springframework.org/schema/util"
		        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    -->
    <util:properties id="prop">
        <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
        <prop key="url">jdbc:mysql://localhost:3306/spring6</prop>
        <prop key="username">root</prop>
        <prop key="password">123</prop>
    </util:properties>

    <!--数据源1-->
    <bean id="ds1" class="com.powernode.spring6.jdbc.MyDataSource1">
        <property name="properties" ref="prop"/>
    </bean>

    <!--数据源2-->
    <bean id="ds2" class="com.powernode.spring6.jdbc.MyDataSource2">
        <property name="properties" ref="prop"/>
    </bean>

</beans>

XML-based autowiring

  • Spring can also complete automated injection, which is also called automatic assembly.
  • It can be automatically assembled based on name or automatically assembled based on type.

Automatically assemble based on name

  • If assembled based on name (byName), the bottom layer will call the set method for injection.
  • For example: the corresponding name of setAge() is age, the corresponding name of setPassword() is password, and the corresponding name of setEmail() is email.
public class OrderDao {
    
    

    private static final Logger logger = LoggerFactory.getLogger(OrderDao.class);

    public void insert(){
    
    
        logger.info("订单正在生成....");
    }
}
public class OrderService {
    
    

    private OrderDao orderDao;

    // 通过set方法给属性赋值。
    public void setOrderDao(OrderDao orderDao) {
    
    
        this.orderDao = orderDao;
    }

    /**
     * 生成订单的业务方法。。。
     */
    public void generate(){
    
    
        orderDao.insert();
    }
}
<!--根据名字进行自动装配-->
<!--注意:自动装配也是基于set方式实现的。-->
<bean id="orderService" class="com.powernode.spring6.service.OrderService" autowire="byName"></bean>

<!--id一般也叫作bean的名称。-->
<!--根据名字进行自动装配的时候,被注入的对象的bean的id不能随便写,
		set方法的方法名去掉set,剩下单词首字母小写。-->
<bean id="orderDao" class="com.powernode.spring6.dao.OrderDao"/>
  • Autowire="byName" needs to be added to the OrderService Bean, which means automatic assembly by name.
  • There is an OrderDao attribute in the OrderService class, and the name of the OrderDao attribute is orderDao, and the corresponding set method is setOrderDao(), which is exactly the same as the id of the OrderDao Bean and can be automatically assembled according to the name.

Automatic assembly based on type

  • Whether it is byName or byType, they are based on the set method during assembly, so the set method must be provided, and it is not possible to provide a constructor method.
  • If byType, when assembling according to type, if there are two beans of the same type in the configuration file, an error will be reported.
  • When byType performs automatic assembly, a certain type of Bean in the configuration file must be unique and cannot appear multiple.
    • If there are multiple beans of the same type, Spring will not know which bean to use for injection.
public class CustomerService {
    
    

    private UserDao userDao;
    private VipDao vipDao;

    public void setUserDao(UserDao userDao) {
    
    
        this.userDao = userDao;
    }

    public void setVipDao(VipDao vipDao) {
    
    
        this.vipDao = vipDao;
    }

    public void save(){
    
    
        userDao.insert();
        vipDao.insert();
    }

}
    <!--根据类型进行自动装配-->
    <!--自动装配是基于set方法的-->
    <!--根据类型进行自动装配的时候,在有效的配置文件当中,某种类型的实例只能有一个。-->
    <bean class="com.powernode.spring6.dao.VipDao"></bean>
    <bean id="x" class="com.powernode.spring6.dao.UserDao"></bean>
    <!--如果byType,根据类型装配时,如果配置文件中有两个类型一样的bean会报错-->
    <!--<bean id="y" class="com.powernode.spring6.dao.UserDao"></bean>-->
    <bean id="cs" class="com.powernode.spring6.service.CustomerService" autowire="byType"></bean>

Spring introduces external property configuration files

  • We all know that when writing a data source, we need information to connect to the database, such as: driver url username password and other information. Can this information be written separately into a property configuration file, so that it will be more convenient for users to modify it?
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring6
jdbc.username=root
jdbc.password=123
<?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">

    <!--
        引入外部的properties文件
        第一步:引入context命名空间。
          xmlns:context="http://www.springframework.org/schema/context"
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        第二步:使用标签context:property-placeholder的location属性来指定属性配置文件的路径。
                    location默认从类的根路径下开始加载资源。
    -->
    <context:property-placeholder location="jdbc.properties"/>

    <!--配置数据源-->
    <bean id="ds" class="com.powernode.spring6.jdbc.MyDataSource">
        <!--怎么取值呢?第三步:${key}-->
        <property name="driver" value="${jdbc.driverClass}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <!--加前缀是由于spring加载变量是优先从系统变量中进行加载,username系统变量已经存在-->
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

</beans>

Guess you like

Origin blog.csdn.net/m0_53022813/article/details/132057743