Spring 框架学习(二)Spring Bean 的装配与注入

Bean 的装配与注入

在 xml 中进行显式配置

最初的引入案例便是在xml中的显式配置。从引入的步骤我们可以了解到,在使用 xml 显式的装配一个 Bean 时,需要以下几个步骤。

  • step1: 首先,创建一个类,这个类可以看做是一个 Bean 的模板。
  • step2: 使用 xml 文件声明一个 Bean。这其中需要指定 Bean 所需要的类,并且为 Bean 指定一个 id 以区分其他的 Bean。
  • step3: 配置 Bean。也就是通过 xml 为已经声明的 Bean 提供可以使用的参数。
  • step4: 调用 Bean。容器自动读取 xml 中 Bean 的配置,并且实例化为应用的上下文,所有的 Bean 的实例都将会从上下文中获取到。
    在接下来的内容中将会讲解其他的通过 xml 进行配置的方法

1. 基于构造器进行相应的配置

i) constructor-arg 标签

在引入的案例中,我们并没有进行 Bean 的注入,接下来的代码,我们将会将配置与注入一起实现。
使用构造器进行配置时,一定要有带参的构造函数。在使用 xml 文档进行配置时,使用标签。

Step1:创建两个 Bean 的实体相关的类

Pen类

package cn.deu.just.demo1;

public class Pen {
	private int id;
	private String brand;
	private double price;
	
	public Pen(int id, String brand, double price) {
		super();
		this.id = id;
		this.brand = brand;
		this.price = price;
	}

	@Override
	public String toString() {
		return "Pen [id=" + id + ", brand=" + brand + ", price=" + price + "]";
	}
	
}

Student类

package cn.deu.just.demo1;

public class Student {
	
	private int id;
	private String name;
	private int age;
	private boolean sex;
	
	private Pen pen;

	public Student(int id, String name, int age, boolean sex, Pen pen) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.pen = pen;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", pen=" + pen + "]";
	}

}

Step2:在 xml 中配置 Bean

在 constructor-arg 标签中 name 与构造函数的变量名相一致,value 代表为该变量名赋上的值。为了避免出错,建议 name 的属性值,与构造函数的参数列表和 POJO 对象的属性名称相一致。

<?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">
	
	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso" class="cn.deu.just.demo1.Pen">
		<constructor-arg name="brand" value="picasso"></constructor-arg>
		<constructor-arg name="id" value="1"></constructor-arg>
		<constructor-arg name="price" value="169.05"></constructor-arg>
	</bean>
	
	<!-- 配置 Student 的  Bean -->
	<bean id="student" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
		<constructor-arg name="pen" ref="picasso"></constructor-arg>
	</bean>

</beans>

Step3:测试

package cn.edu.stu.test;

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

import cn.deu.just.demo1.Student;

public class StudentTest {
	
	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo1Context.xml");
		Student stu = (Student)ctx.getBean("student");
		System.out.println(stu);
		
	}

}

2. 基于 get 函数的装配

property 标签

property 则不必要像 constructor-arg 那样必须要依靠构造函数,只需要借助相应的 get 与 set 方法。

Step1:首先对 Student 类进行改动

package cn.deu.just.demo1;

import java.util.List;

public class Student {
	
	private int id;
	private String name;
	private int age;
	private boolean sex;
	private Pen pen;
	
	public Student(int id, String name, int age, boolean sex) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	
	
	public Pen getPen() {
		return pen;
	}


	public void setPen(Pen pen) {
		this.pen = pen;
	}


	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", pen=" + pen + "]";
	}

}

Step2:在 XML 中进行 Bean 的配置

<?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">

	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso1" class="cn.deu.just.demo1.Pen">
		<constructor-arg name="brand" value="picasso"></constructor-arg>
		<constructor-arg name="id" value="1"></constructor-arg>
		<constructor-arg name="price" value="169.05"></constructor-arg>
	</bean>

	<!-- 配置 Student 的 Bean -->
	<bean id="student1" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
	</bean>
	
	<bean id="student2" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="李四"></constructor-arg>
		<constructor-arg name="age" value="17"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
		<property name="pen" ref="picasso1"></property>
	</bean>

</beans>

Step3:测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo1Context.xml");
		Student stu1 = (Student)ctx.getBean("student1");
		Student stu2 = (Student)ctx.getBean("student2");
		System.out.println(stu1);
		System.out.println(stu2);
	}

结果显示

Student [id=19092701, name=张三, age=22, sex=true, pen=null]
Student [id=19092701, name=李四, age=17, sex=true, pen=Pen [id=1, brand=picasso, price=169.05]]

3. 配置的简便写法

i) 使用 C 命名空间

c 命名空间 的使用要在 beans 中添加 xmlns:c="http://www.springframework.org/schema/c"这行代码就可以引入
c 命名空间对一般变量进行赋值时要 c: 加上相应的变量名称,然后要赋的值直接放在等号后。而如果是 Bean 的注入则需要 c: 加上相应的变量名称再加上 -ref
不过需要注意 c 命名空间中的变量必须和构造器相对应,也就说 c 命名空间是 constructor-arg 的一种简写形式

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

	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso1" class="cn.deu.just.demo1.Pen" 
		c:brand="picasso"
		c:id="1"
		c:price="169.05"/>

	<!-- 配置 Student 的 Bean -->
	<bean id="student1" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
	</bean>
	
	<bean id="student2" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="李四"></constructor-arg>
		<constructor-arg name="age" value="17"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
		<property name="pen" ref="picasso1"></property>
	</bean>

</beans>

ii) 使用 P 命名空间

其实 p 命名空间也就是 property 的一种简写形式
在使用 p 命名空间时 需要在 beans 中加入 xmlns:p="http://www.springframework.org/schema/p"

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:c="http://www.springframework.org/schema/c"
	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">

	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso1" class="cn.deu.just.demo1.Pen" 
		c:brand="picasso"
		c:id="1"
		c:price="169.05"/>

	<!-- 配置 Student 的 Bean -->
	<bean id="student1" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
	</bean>
	
	<bean id="student2" class="cn.deu.just.demo1.Student" 
		p:pen-ref="picasso1">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="李四"></constructor-arg>
		<constructor-arg name="age" value="17"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
	</bean>

</beans>

4. 配置时对于泛型的处理

i) list 类型

当然,也有一个 Bean 需要多个 Bean 的时候,此时就需要在 Bean 中构造一个 列表

Step1:创建两个 Bean 的实体相关的类

此时需要对 Student 类进行些许改动
Student类

package cn.deu.just.demo1;

import java.util.List;

public class Student {
	
	private int id;
	private String name;
	private int age;
	private boolean sex;
	
	private List<Pen> pens;

	public Student(int id, String name, int age, boolean sex, List<Pen> pens) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.pens = pens;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", pens=" + pens + "]";
	}

}

Step2:在 XML 中进行 Bean 的配置

对于 Bean 的列表的配置 此时需要在 constructor-arg 标签下,放入 list 标签,其中 value 是相应值的列表子项标签,ref 是注入的 Bean 的子标签。

<?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">

	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso1" class="cn.deu.just.demo1.Pen">
		<constructor-arg name="brand" value="picasso"></constructor-arg>
		<constructor-arg name="id" value="1"></constructor-arg>
		<constructor-arg name="price" value="169.05"></constructor-arg>
	</bean>

	<bean id="picasso2" class="cn.deu.just.demo1.Pen">
		<constructor-arg name="brand" value="picasso"></constructor-arg>
		<constructor-arg name="id" value="2"></constructor-arg>
		<constructor-arg name="price" value="788.65"></constructor-arg>
	</bean>

	<bean id="hero" class="cn.deu.just.demo1.Pen">
		<constructor-arg name="brand" value="hero"></constructor-arg>
		<constructor-arg name="id" value="3"></constructor-arg>
		<constructor-arg name="price" value="25.00"></constructor-arg>
	</bean>

	<!-- 配置 Student 的 Bean -->
	<bean id="student" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
		<constructor-arg name="pens">
			<list>
				<ref bean="picasso1" />
				<ref bean="picasso2" />
				<ref bean="hero" />
			</list>
		</constructor-arg>
	</bean>

</beans>

Step3: 测试

package cn.edu.stu.test;

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

import cn.deu.just.demo1.Student;

public class StudentTest {
	
	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo1Context.xml");
		Student stu = (Student)ctx.getBean("student");
		System.out.println(stu);
		
	}

}

运行结果

Student [id=19092701, name=张三, age=22, sex=true, 
pens=[Pen [id=1, brand=picasso, price=169.05], 
Pen [id=2, brand=picasso, price=788.65], 
Pen [id=2, brand=hero, price=25.0]]]
ii) Map 类型

Step1:Student类进行改动

package cn.deu.just.demo1;

import java.util.Map;

public class Student {
	
	private int id;
	private String name;
	private int age;
	private boolean sex;
	private Map<String,Pen> pens;
	
	public Student(int id, String name, int age, boolean sex) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public Map<String, Pen> getPens() {
		return pens;
	}


	public void setPens(Map<String, Pen> pens) {
		this.pens = pens;
	}

	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", pen=" + pens + "]";
	}
	

}

Step2:在配置文件中进行配置

<?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"
	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">

	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso1" class="cn.deu.just.demo1.Pen" 
		c:brand="picasso"
		c:id="1"
		c:price="169.05"/>
	
	<bean id="picasso2" class="cn.deu.just.demo1.Pen" 
		c:brand="picasso"
		c:id="2"
		c:price="397.45"/>
		
	<bean id="hero" class="cn.deu.just.demo1.Pen" 
		c:brand="hero"
		c:id="3"
		c:price="54.00"/>
	
	<!-- 配置 Student 的 Bean -->
	<bean id="student1" class="cn.deu.just.demo1.Student">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
		<property name="pens">
			<map>
				<entry key="AA" value-ref="picasso1"></entry>
				<entry key="BB" value-ref="picasso2"></entry>
				<entry key="CC" value-ref="hero"></entry>
			</map>
		</property>
	</bean>
	
</beans>

Step3:测试

    @Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo1Context.xml");
		Student stu1 = (Student)ctx.getBean("student1");
		System.out.println(stu1);
	}

运行结果

Student [id=19092701, name=张三, age=22, sex=true, pen={
AA=Pen [id=1, brand=picasso, price=169.05], 
BB=Pen [id=2, brand=picasso, price=397.45], 
CC=Pen [id=3, brand=hero, price=54.0]
}]

在 Java 中进行显式配置

Step1: 创建 Bean 类

Student 类

package cn.edu.stu.Demo2.Bean;

import java.util.Map;

public class Student {
	
	private int id;
	private String name;
	private int age;
	private boolean sex;
	private Pen pen;
	
	public Student(int id, String name, int age, boolean sex) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	
	public Pen getPen() {
		return pen;
	}

	public void setPen(Pen pen) {
		this.pen = pen;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", pen=" + pen + "]";
	}
	

}

Pen 类

package cn.edu.stu.Demo2.Bean;

public class Pen {
	private int id;
	private String brand;
	private double price;
	
	public Pen(int id, String brand, double price) {
		super();
		this.id = id;
		this.brand = brand;
		this.price = price;
	}

	@Override
	public String toString() {
		return "Pen [id=" + id + ", brand=" + brand + ", price=" + price + "]";
	}
	
}

Step2:使用 java 类配置

要使用 Java 类配置 Bean 要在配置的类前使用 @Configuration 注解。该注解将该类标致成为一个 Java 类。
对于内部的 Bean 的配置,可以使用 @Bean 注解,将某个函数标注成为一个 Bean。默认情况下 Bean 的 id 与函数名相同,当然也可以通过 name 来自己设定 Bean 的 id。
在使用类配置时 Bean 的注入只能通过调用相应的函数,不能使用其他方式。

package cn.edu.stu.Demo2.Config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.edu.stu.Demo2.Bean.Pen;
import cn.edu.stu.Demo2.Bean.Student;

@Configuration
public class StuConfig {
	
	@Bean
	public Pen picasso1() {
		Pen pen = new Pen(1,"picasso",165.05);
		return pen;
	}
	
	@Bean(name="hero")
	public Pen getPen() {
		Pen pen = new Pen(2,"hero",54.50);
		return pen;
	}
	
	@Bean(name="stu1")
	public Student stu1() {
		Student stu = new Student(1,"张三",22,true);
		//Bean 的注入类似于函数的调用
		stu.setPen(picasso1());
		return stu;
	}

}

Step3:测试

此时读入 Bean 的配置类的函数为 AnnotationConfigApplicationContext 函数。

    @Test
	public void Test2() {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(StuConfig.class);
		Pen pen1 = (Pen)ctx.getBean("picasso1");
		Pen pen2 = (Pen)ctx.getBean("hero");
		Student stu1 = (Student)ctx.getBean("stu1");
		System.out.println(pen1);
		System.out.println(pen2);
		System.out.println(stu1);
	}

测试结果

Pen [id=1, brand=picasso, price=165.05]
Pen [id=2, brand=hero, price=54.5]
Student [id=1, name=张三, age=22, sex=true, pen=Pen [id=1, brand=picasso, price=165.05]]

隐式 Bean 的发现机制

当然除了上述可以被发现的方式之外,我们还可以实现 Bean 的自动发现和自动创建。

创建可被发现的 Bean

在实现自动发现并且装配之前,一定需要标注那些类是可以作为 Bean。这些类就需要用 @Component 注解进行标识,能够使这些类被自动的发现。
当然 @Component 还可以为 Bean 指定 id。
同时 @Component 还可以使用 @Named 替代。

创建两个可被发现的 Bean

以下两个类中分别是有一个有参构造函数,一个无参构造函数,以及 get , set 与 toSting 函数。还有一个 show( ) 函数用以检测这两个被标注的 Bean 是否被实例化。
Pen 类

package cn.edu.stu.Demo3.Bean;

import org.springframework.stereotype.Component;

@Component("picasso")
public class Pen {
	private int id;
	private String brand;
	private double price;
	
	
	public Pen() {
		super();
	}


	public Pen(int id, String brand, double price) {
		super();
		this.id = id;
		this.brand = brand;
		this.price = price;
	}
	
	
	public int getId() {
		return id;
	}


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


	public String getBrand() {
		return brand;
	}


	public void setBrand(String brand) {
		this.brand = brand;
	}


	public double getPrice() {
		return price;
	}


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

	public void show() {
		System.out.println("This is a Pen Bean");
	}
	
	@Override
	public String toString() {
		return "Pen [id=" + id + ", brand=" + brand + ", price=" + price + "]";
	}
	
}

Student 类

package cn.edu.stu.Demo3.Bean;

import org.springframework.stereotype.Component;

@Component
public class Student {
	
	private int id;
	private String name;
	private int age;
	private boolean sex;
	private Pen pen;
	
	
	public Student() {
		super();
	}


	public Student(int id, String name, int age, boolean sex) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	
	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 boolean isSex() {
		return sex;
	}


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


	public Pen getPen() {
		return pen;
	}

	public void setPen(Pen pen) {
		this.pen = pen;
	}

	public void show() {
		System.out.println("This is a Student Bean");
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", pen=" + pen + "]";
	}
	

}

基于 xml 实现 Bean 自动发现装配

要使用 xml 配置文件实现自动装配 Bean ,就要用到 context:component-scan 标签,并且用 package 属性指定 Bean 所属的包。
在使用 context:component-scan 标签前,需要在 xml 中引入 context 命名空间,即在 Bean标签中加入

xmlns:context="http://www.springframework.org/schema/context"

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: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-4.3.xsd">

	<context:component-scan base-package="cn.edu.stu.Demo3.Bean"></context:component-scan>

</beans>

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo3Context.xml");
		Student stu1 = (Student)ctx.getBean("student");
		Pen pen = (Pen)ctx.getBean("picasso");
		stu1.show();
		pen.show();
	}

运行结果

This is a Student Bean
This is a Pen Bean

基于 java 配置类实现 Bean 自动发现装配

在 Java 类中实现自动化扫描需要使用 @ComponentScan 注解。
默认情况下被标注 @ComponentScan 注解的类会自动扫描自己所在包的 Bean。当然 ComponentScan 也可以通过 basePackage 来指定自动扫描的包
例如

@ComponentScan( basePackage="cn.edu.stu.Bean")
或
@ComponentScan( "cn.edu.stu.Bean")

当然也可以指定多个包

@ComponentScan( basePackage={"cn.edu.stu.Bean", "cn.edu.stu.Bean"})

当然如果只扫描包中的某几个类的话

@ComponentScan( basePackageClasses={Student.class , Pen.class})

Java 配置文件

package cn.edu.stu.Demo3.Config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("cn.edu.stu.Demo3.Bean")
public class StuConfig {

}

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(StuConfig.class);
		Student stu1 = (Student)ctx.getBean("student");
		Pen pen = (Pen)ctx.getBean("picasso");
		stu1.show();
		pen.show();
	}

结果

This is a Student Bean
This is a Pen Bean

自动装配

自动装配可以无需手动设置,就可以自动实现 Bean 的注入
自动装配的形式有两种,一种是使用 xml 进行装配,另一种是 java 配置类通过注解的方式实现装配。

使用 xml 进行自动装配

在使用 xml 文件进行自动装配,需要在 Bean 标签中使用使用 autowire 属性。autowire 有两个可以取的值 byName 和 byType

byName

autowire 取 byName 意味着将会按照 id 名称装配(注入)需要的 Bean。

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


	<!-- 配置 Pen 的 Bean -->
	<bean id="pen" class="cn.edu.stu.Demo3.Bean.Pen" 
		c:brand="picasso"
		c:id="1"
		c:price="169.05"/>
		
	<!-- 配置 Student 的 Bean -->
	<bean id="student1" class="cn.edu.stu.Demo3.Bean.Student" autowire="byName">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
	</bean>
</beans>

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo3Context.xml");
		Student stu1 = (Student)ctx.getBean("student1");
		System.out.println(stu1);
	}

结果

Student [id=19092701, name=张三, age=22, sex=true, 
pen=Pen [id=1, brand=picasso, price=169.05]]

当然如果将 xml 中的 pen 改为 pen1,或者 pen2 都不会成功,

byType

autowire 取 byType 意味着会按照 Bean 所属的类型进行自动装配,不必在乎 Bean 的 id,但是前提,配置文件中只有一个该类型的 Bean。

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


	<!-- 配置 Pen 的 Bean -->
	<bean id="picasso" class="cn.edu.stu.Demo3.Bean.Pen" 
		c:brand="picasso"
		c:id="1"
		c:price="169.05"/>
		
	<!-- 配置 Student 的 Bean -->
	<bean id="student1" class="cn.edu.stu.Demo3.Bean.Student" autowire="byType">
		<constructor-arg name="id" value="19092701"></constructor-arg>
		<constructor-arg name="name" value="张三"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
		<constructor-arg name="sex" value="true"></constructor-arg>
	</bean>
</beans>

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo3Context.xml");
		Student stu1 = (Student)ctx.getBean("student1");
		System.out.println(stu1);
	}

结果

Student [id=19092701, name=张三, age=22, sex=true, 
pen=Pen [id=1, brand=picasso, price=169.05]]

使用 Java 注解实现自动装配

在已被 @Component 注解标注的 Bean 中,凡是有 Bean 的注入有关的函数(构造函数或者是 set 函数)使用 @Autowired 注解,就可以实现自动装配。

在 Student 的 Bean 中加入 @Autowired 注解

     @Autowired
     public void setPen(Pen pen) {
           this.pen = pen;
     }

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(StuConfig.class);
		Student stu1 = (Student)ctx.getBean("student");
		Pen pen =stu1.getPen();
		pen.show();
	}

运行结果

This is a Pen Bean

工厂方法配置 Bean

工厂方法配置 Bean 的方式有两种,一种是静态工厂配置,另一种是实例化工厂配置。

静态工厂配置 Bean

创建静态工厂类

首先要创建一个静态的工厂方法,这个方法中包括可以被获取的 bean 。

package cn.edu.stu.Demo4.BeanFactory;

import java.util.HashMap;
import java.util.Map;


import cn.edu.stu.Demo4.Bean.Pen;

public class StaticPenFactory {
	private static Map<String,Pen>  pens = new HashMap<String,Pen>();
	
	static {
		pens.put("picasso1", new Pen(1,"picasso",163.05));
		pens.put("picasso2", new Pen(2,"picasso",765.45));
		pens.put("hero",new Pen(3,"Hero",45.00));
	}
	
	public static Pen getPen(String name) {
		return pens.get(name);
	}

}

配置 xml 文件

此时用 class 属性指定工厂类,用 factory-method 指向工厂获取 Bean 的方法。

<?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">

	<bean id="pen" class="cn.edu.stu.Demo4.BeanFactory.StaticPenFactory" factory-method="getPen">
		<constructor-arg value="hero"></constructor-arg>
	</bean>

	
</beans>

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo4Context.xml");
		Pen pen = (Pen)ctx.getBean("pen");
		System.out.println(pen);
	}

结果

Create a new Pen Bean
Create a new Pen Bean
Create a new Pen Bean
Pen [id=3, brand=Hero, price=45.0]

实例化工厂配置 Bean

创建示例化工厂

package cn.edu.stu.Demo4.BeanFactory;

import java.util.HashMap;
import java.util.Map;

import cn.edu.stu.Demo4.Bean.Pen;

public class InstancePenFactory {

	private Map<String,Pen> pens;

	public InstancePenFactory() {
		super();
		this.pens = new HashMap<String,Pen>();
		pens.put("picasso1", new Pen(1,"picasso",163.05));
		pens.put("picasso2", new Pen(2,"picasso",765.45));
		pens.put("hero",new Pen(3,"Hero",45.00));
	}
	
	public Pen getPen(String name) {
		return pens.get(name);
	}
	
	
}

配置 xml 文件

在配置实例化 Bean 工厂的 xml 时,要注意为工厂类单独建立一个 Bean,需要获取的 Bean 将会从工厂 Bean 中读出。

<?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">

	<bean id="penFactory" class="cn.edu.stu.Demo4.BeanFactory.InstancePenFactory"></bean>
	
	<bean id="pen" factory-bean="penFactory" factory-method="getPen">
		<constructor-arg value="picasso1"></constructor-arg>
	</bean>

	
</beans>

测试

	@Test
	public void Test1() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("BeanDemo4Context.xml");
		Pen pen = (Pen)ctx.getBean("pen");
		System.out.println(pen);
	}

结果

Create a new Pen Bean
Create a new Pen Bean
Create a new Pen Bean
Pen [id=1, brand=picasso, price=163.05]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

求和的小熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值