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]