Spring使用set注入为属性赋值

  • set注入
    • 简单类型的注入
    • 引用类型的注入
  • 构造注入
  • 自动注入
    • 按照名称进行注入
    • 按照类型注入
    • 按照构造自动注入

注入就是赋值的意思
Spring规定:Java中的基本数据类型和字符串都是简单数据类型
set注入的本质是调用set方法来赋值,因此在使用此方法注入时set方法必不可少

 

set注入

简单类型的注入

先创建一个简单的Hello类,定义一个属性及其的set方法

public class Hello {
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

在xml文件里使用set注入为Hello类里面的属性赋值
切记别名不可重复

    <!--id是对象的别名,class是绝对路径-->
    <bean id="hello" class="spring.service.ba01.Hello">
        <!--name是属性名,value属性值-->
        <property name="msg" value="Hello world"/>
    </bean>

在HelloWorld类里面实例化出Hello类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloWorld {
    public static void main(String[] args) {
        //存储xml文件的路径
        String config = "ba01/ba01.xml";
        //生成ac,以便于实例化对象
        ApplicationContext ac =new ClassPathXmlApplicationContext(config);
        //实例化对象,hello就是xml文件中给Hello起的别名
        Hello hello = (Hello)ac.getBean("hello");
        System.out.println(hello.getMsg());
    }
}

结果如图所示,Hello已被实例化出来了
【Spring】Spring使用xml注入为属性赋值_spring boot
集合属性注入

//在Hello类加入属性
private List<String>list;
private Set<String> set;
private Map<String, String> map;

xml文件配置

<property name="list">
            <list>
                <value>a</value>
                <value>b</value>
                <value>c</value>
            </list>
        </property>
                <property name="map">
            <map>
                <entry key="a" value="aaa"></entry>
                <entry key="b" value="bbb"></entry>
            </map>
        </property>
        <property name="set">
            <set>
                <value>1</value>
                <value>2</value>
                <value>1</value>
            </set>
        </property>

结果

【Spring】Spring使用xml注入为属性赋值_spring_02

引用类型的注入

创建school类

public class school {
   private String name;
   private String address;

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

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

创建student类

public class student {
    private school school;
    private String name;

    @Override
    public String toString() {
        return "我叫:"+getName()+",我在位处于:"+school.getAddress()+"的名字叫:"+school.getName()+"上学";
    }

    public spring.service.ba01.school getSchool() {
        return school;
    }

    public void setSchool(spring.service.ba01.school school) {
        this.school = school;
    }

    public String getName() {
        return name;
    }

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

编写xml文件

    <bean id="school" class="spring.service.ba01.school">
        <property name="name" value="清华"/>
        <property name="address" value="北京"/>
    </bean>
    
    <bean id="student" class="spring.service.ba01.student">
        <property name="name" value="张三"/>
        <property name="school" ref="school"/>
    </bean>

编写测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        String config = "ba01/ba01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        student student = (student)ac.getBean("student");
        System.out.println(student);
    }
}

测试结果如图赋值成功
【Spring】Spring使用xml注入为属性赋值_java_03

构造注入

构造注入即使用构造方法注入,而不使用set方法,也就是说不一定必须要写set方法,但是有参构造必须存在
创建Student类和School类

public class School {
    private String name;
    private String address;

    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
public class Student {
    private School school;
    private String name;
    private int age;

    public Student(School school, String name, int age) {
        this.school = school;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "school=" + school +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在xml文件里使用构造注入为属性赋值

	<bean id="SC" class="com.demo.test1.School">
		<constructor-arg name="address" value="北京"></constructor-arg>
		<constructor-arg name="name" value="北大"></constructor-arg>
	</bean>
	<bean id="stu" class="com.demo.test1.Student">
		<constructor-arg index="0" ref="SC"></constructor-arg>
		<constructor-arg index="1" value="张三"></constructor-arg>
		<constructor-arg index="2" value="20"></constructor-arg>
	</bean>

上述代码可以看出,构造注入的俩种写法,一种是name使用属性名来确定属性,另一种使用index,他是从0开始计算的
测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args) {
		String config = "classpath:spring/ApplicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(config);
		Student student = (Student)ac.getBean("stu");
		System.out.println(student);
	}
}

结果

【Spring】Spring使用xml注入为属性赋值_spring boot_04

自动注入

自动注入是采用约定大约配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。

xml中可以在bean元素中通过autowire属性来设置自动注入的方式,autowire分为三种按照名称进行注入、按照类型进行注入和按照构造方法进行注入


按照名称进行注入

spring容器会按照set属性的名称去容器中查找同名的bean对象,然后将查找到的对象通过set方法注入到对应的bean中,未找到对应名称的bean对象则set方法不进行注入


创建Student和School类

public class Student {
	private School school;
	private String name;
	private String age;

	public School getSchool() {
		return school;
	}

	public void setSchool(School school) {
		this.school = school;
	}

	public String getName() {
		return name;
	}

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

	public String getAge() {
		return age;
	}

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

	@Override
	public String toString() {
		return "Student [school=" + school + ", name=" + name + ", age=" + age + "]";
	}
}
public class School {
	private String address;
	private String name;

	public String getAddress() {
		return address;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "School [address=" + address + ", name=" + name + "]";
	}
}

编写xml文件

	<bean id="sc" class="com.demo.autowire.School">
		<property name="address" value="北京"></property>
		<property name="name" value="北大"></property>
	</bean>

	<bean id="mystu" class="com.demo.autowire.Student" autowire="byName">
		<property name="age" value="20"></property>
		<property name="name" value="张三"></property>
	</bean>

byName是根据名字来赋值,所以id名要和参数一致才可,列如此处的Student类中并没有为school属性赋值,我们准备使用byName自动赋值,那么我们在写xml文件的时候给school类的id必须和student类里school的属性名称一样才能完成赋值


测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.demo.autowire.*;

public class Test {
	public static void main(String[] args) {
		String config = "classpath:spring/ApplicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(config);
		Student student = (Student) ac.getBean("mystu");
		System.out.println(student);
	}
}

结果如图所示赋值成功
【Spring】Spring使用xml注入为属性赋值_ioc_05


按照类型注入


spring容器会遍历x类中所有的set方法,会在容器中查找和set参数类型相同的bean对象,将其通过set方法进行注入,未找到对应类型的bean对象则set方法不进行注入。

需要注入的set属性的类型和被注入的bean的类型需要满足isAssignableFrom关系。

按照类型自动装配的时候,如果按照类型找到了多个符合条件的bean,系统会报错。父子类实现关系都算同种

set方法的参数如果是下面的类型或者下面类型的数组的时候,这个set方法会被跳过注入:


创建Game类和User类

public class User {
	private Game game;
	private String name;

	public Game getGame() {
		return game;
	}

	public void setGame(Game game) {
		this.game = game;
	}

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "User [game=" + game + ", name=" + name + "]";
	}
}
public class Game {
	private String name;

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "Game [name=" + name + "]";
	}
}

编写xml文件

	<bean id="game" class="com.demo.autowire_type.Game">
		<property name="name" value="王者荣耀"></property>
	</bean>

	<!-- byType是按照类型自动赋值,在本例中我们需要自动赋值Game,他就会在xml文件里查找类型为game的,但是同种类型只能存在一个,实现类,父子类都算同种类型 
		也就是说,在这个xml文件里只可以存在一个game类。他的父子类,实现类都不能存在 -->
	<bean id="user" class="com.demo.autowire_type.User" autowire="byType">
		<property name="name" value="张三"></property>
	</bean>

测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.demo.autowire.*;

public class Test {
	public static void main(String[] args) {
		String config = "classpath:spring/ApplicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(config);
		User user = (User) ac.getBean("user");
		System.out.println(user);
	}
}

结果

【Spring】Spring使用xml注入为属性赋值_spring_06
Game类的name被自动赋值了


按照构造自动注入

spring会找到x类中所有的构造方法(一个类可能有多个构造方法),然后将这些构造方法进行排序(先按修饰符进行排序,public的在前面,其他的在后面,如果修饰符一样的,会按照构造函数参数数量倒叙,也就是采用贪婪的模式进行匹配,spring容器会尽量多注入一些需要的对象)得到一个构造函数列表,会轮询这个构造器列表,判断当前构造器所有参数是否在容器中都可以找到匹配的bean对象,如果可以找到就使用这个构造器进行注入,如果不能找到,那么就会跳过这个构造器,继续采用同样的方式匹配下一个构造器,直到找到一个合适的为止。


创建Game类和User类

public class User {
	private Game game;
	private String name;

	public Game getGame() {
		return game;
	}

	public void setGame(Game game) {
		this.game = game;
	}

	public String getName() {
		return name;
	}

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

	public User(Game game) {
		super();
		this.game = game;
	}

	@Override
	public String toString() {
		return "User [game=" + game + ", name=" + name + "]";
	}
}
public class Game {
	private String name;

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "Game [name=" + name + "]";
	}
}

编写xml文件

	<bean id="Game" class="com.demo.autowire_con.Game">
		<property name="name" value="王者荣耀"></property>
	</bean>

	<!-- 构造注入会采用贪婪模式,最大限度地注入属性,即当一个构造要注入三个,一个要注入俩个,会选择第一个 -->
	<bean id="user" class="com.demo.autowire_con.User" autowire="constructor">
		<property name="name" value="张三"></property>
	</bean>

测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.demo.autowire_con.*;

public class Test {
	public static void main(String[] args) {
		String config = "classpath:spring/ApplicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(config);
		User user = (User) ac.getBean("User");
		System.out.println(user);
	}
}

结果,如图,构造注入赋值成功
【Spring】Spring使用xml注入为属性赋值_java_07