【目录】
3.1 XML文件最基本的元素:Bean元素
3.1.1 Bean元素基本属性
3.1.2 Bean标签创建方式
3.1.3 Bean的生命周期
3.2 Bean元素的注入方式
3.2.1 set方法属性注入
3.2.2 构造器参数注入
3.2.3 注入复杂类型
3.1 XML文件最基本的元素:Bean元素
Bean元素:交由Spring管理的对象都要配置在bean标签中。
3.1.1 Bean元素基本属性
示例代码:
具体说明:
- id:bean的名称(对象的名称),在应用程序中,可以根据id值得到配置对象。id的名字必须满足XML的命名规范,不能包含特殊字符或中文,习惯上会使用接口的名字小写。注意:id名在整个Spring的配置文件中,必须唯一。
- name:为id创建一个或多个别名,可以包含特殊符号。
注意:id和name都可以指定多个名字,名字之间可用逗号、分号、或者空格间隔。
- class:是实现类的全名(填写创建对象所在类的全路径),Spring工厂会自动根据该类型名字,采用反射机制来得到具体的类的类型。
- scope:bean的作用范围。有以下5个常用属性值:
(1)singleton:默认值,表示整个IOC容器共享一个Bean,也就是说每次说每次通过getBean获取的bean都是同一个。
(2)prototype:每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
(3)request:在web项目中,创建对象并把对象放到request域里面,每次HTTP请求将会生成各自的bean实例。
(4)session :在web项目中,创建对象并把对象放到到session域中,每次会话请求对应一个bean实例。
(5)globalSession:在web项目中,应用在prolet环境,如果没有prolet环境那么globalSession相当于session。一般用于全局session共享账号。
补充:延迟加载
3.1.2 Bean标签创建方式
- 空参构造:最常用的创建方式。
过程很简单,就是在类中创建一个无参数的构造方法。
例如:
public class User {
public User() {
}
}
一般来说,如果不写无参数的参构造方法,也没有关系,因为在类中会默认有一个隐藏的无参构造方法(不显示在代码中)。
但是注意! 如果你在类中定义了带参的构造方法,那么这个类默认的无参的构造方法没有了,需要手动加上去才行。——这牵涉到我们后面的一个知识点:如果采用构造方法的注入方式(后面讲解三种注入方式),就必须把无参数的参构造方法写出来。不然就会报错误:No default constructor found......
所以这里推荐在编写代码时,把无参数的参构造方法都写出来。
- 静态工厂
- 实例工厂
静态工厂和实例工厂的更多内容推荐看这里Spring创建Bean的三种方式的使用和区别。
- FactoryBean方式:源码底层用的多。不作详细介绍了。只需要区别好BeanFactory和FactoryBean:
BeanFactory:是一个工厂(其实是构建了一个spring上下文的环境,容器),用来管理和获取很多Bean对象,
FactoryBean:是一个Bean生成工具,是用来获取一种类型对象的Bean,它是构造Bean实例的一种方式。
总结:以上四种,第一种最常用,第二、三、一些框架初始化的时候用的多、第四种spring底层用的多。
3.1.3 Bean的生命周期
通过 init-method属性 指定初始化的方法。
通过 destroy-method属性 指定销毁对象的方法 。
3.2 Bean元素的注入方式
Bean元素的注入有三种方法,分别是set方法属性注入、构造器参数注入、接口注入 。
(Spring 框架规范中通过配置文件配置的方式,只支持set方法属性注入和构造器参数注入,不支持接口注入,所以这里只讲解前两种注入方式。)
注入类型有值类型(八大基本数据类型)、引用类型(String、自定义对象等)和复杂类型(Array、List、Set、Map、Properties)。
3.2.1 set方法属性注入
在类中加set方法,然后在配置文件中用
(用此方法展示注入值类型和引用类型,后续方法中不再演示。注入复杂类型在3.2.3单独介绍。)
下面开始演示。
1.注入值类型。代码如下。
实体类User.java:
package user;
public class User {
private Integer u_id;
private String u_username;
private String u_password;
//这里是空参构造
public User() {
}
public Integer getU_id() {
return u_id;
}
public void setU_id(Integer u_id) {
this.u_id = u_id;
}
public String getU_username() {
return u_username;
}
public void setU_username(String u_username) {
this.u_username = u_username;
}
public String getU_password() {
return u_password;
}
public void setU_password(String u_password) {
this.u_password = u_password;
}
@Override
public String toString() {
return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password
+ "]";
}
}
配置文件applicationContext_Injection.xml:
测试类 Test_Injection.java:
package user;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test_Injection {
@Test
public void Test() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_Injection.xml");
User u1 = (User) ac.getBean("user");
System.out.println(u1);
//关闭容器
ac.close();
}
}
进行测试。
2.注入引用类型。
在刚刚的工程中新建一个Pet.java,代码如下。
Pet.java:
package user;
public class Pet {
//宠物类型 猫 狗
private String petType;
//宠物的颜色
private String color;
public String getPetType() {
return petType;
}
public void setPetType(String petType) {
this.petType = petType;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Pet [petType=" + petType + ", color=" + color + "]";
}
}
在User.java里加入宠物字段。
User.java:
package user;
public class User {
private Integer u_id;
private String u_username;
private String u_password;
//这里是空参构造
public User() {
}
private Pet u_pet;
public Pet getU_pet() {
return u_pet;
}
public void setU_pet(Pet u_pet) {
this.u_pet = u_pet;
}
public Integer getU_id() {
return u_id;
}
public void setU_id(Integer u_id) {
this.u_id = u_id;
}
public String getU_username() {
return u_username;
}
public void setU_username(String u_username) {
this.u_username = u_username;
}
public String getU_password() {
return u_password;
}
public void setU_password(String u_password) {
this.u_password = u_password;
}
@Override
public String toString() {
return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password + ", u_pet=" + u_pet
+ "]";
}
}
修改配置文件。
applicationContext_Injection.xml:
进行测试。
3.2.2 构造器参数注入
首先在类中编写一个带参数的构造方法,然后在配置文件中用
下面开始演示。
在刚刚的工程中修改User.java,添加一个带参数(String u_username, Pet u_pet)的构造方法。
User.java:
package user;
public class User {
private Integer u_id;
private String u_username;
private String u_password;
//这里是空参构造
public User() {
}
//带参数的构造方法
public User(String u_username, Pet u_pet) {
this.u_username = u_username;
this.u_pet = u_pet;
}
private Pet u_pet;
public Pet getU_pet() {
return u_pet;
}
public void setU_pet(Pet u_pet) {
this.u_pet = u_pet;
}
public Integer getU_id() {
return u_id;
}
public void setU_id(Integer u_id) {
this.u_id = u_id;
}
public String getU_username() {
return u_username;
}
public void setU_username(String u_username) {
this.u_username = u_username;
}
public String getU_password() {
return u_password;
}
public void setU_password(String u_password) {
this.u_password = u_password;
}
@Override
public String toString() {
return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password + ", u_pet=" + u_pet
+ "]";
}
}
修改配置文件。
applicationContext_Injection.xml:
修改测试类。
Test_Injection.java:
package user;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test_Injection {
@Test
public void Test() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_Injection.xml");
User u1 = (User) ac.getBean("user1");
System.out.println(u1);
//关闭容器
ac.close();
}
}
进行测试。
补充:
我们知道,在一个类里,可以进行方法的重载( 重载与重写的区别),构造方法可以有多个。我们怎么让bean精准定位到某一个构造方法呢?这就要用到
- 构造方法参数不同时,用type指定一个不同参数的类型,就可以定位构造方法。
( 有多个构造方法,却不使用type,那么就会自动定位到第一个构造方法。) - 构造方法参数相同,位置不同时,用type和index可以共同指定某个参数的位置(从构造函数第一个参数开始index+,第一个参数的index=0),从而定位构造方法。
(只使用type或index的其中一个——只用type,会定位到更新的那一个构造方法;而index无法单独使用。)
【演示】
修改User.java,添加一个与方法1参数不同的方法2。代码片段如下:
//不同参数的构造
//方法1
public User(String u_username, Pet u_pet) {
System.out.println("方法1 String, Pet");
this.u_username = u_username;
this.u_pet = u_pet;
}
//方法2
public User(Integer u_username, Pet u_pet) {
System.out.println("方法2 Integer, Pet");
this.u_username = u_username.toString();
this.u_pet = u_pet;
}
修改配置文件片段,指定type=Integer。同时,把value改成66,因为要传一个Integer类型的值。
修改User.java,添加一个与方法2参数相同,位置不同的方法3。代码片段如下:
//方法1
public User(String u_username, Pet u_pet) {
System.out.println("方法1 String, Pet");
this.u_username = u_username;
this.u_pet = u_pet;
}
//方法2
public User(Integer u_username, Pet u_pet) {
System.out.println("方法2 Integer, Pet");
this.u_username = u_username.toString();
this.u_pet = u_pet;
}
//方法3
public User(Pet u_pet, Integer u_username) {
System.out.println("方法3 Pet, Integer ");
this.u_username = u_username.toString();
this.u_pet = u_pet;
}
不修改配置文件,仍然只指定type=Integer,可以看到运行结果,定位到方法3而非方法2。
配置文件片段,指定type=Integer和index=0。
运行。
3.2.3 注入复杂类型
注入复杂类型也就是注入集合类型 (Array、List、Set、Map、Properties),属于了解内容,在使用时查看即可。
作用:主要用于框架整合配置。
Spring为集合提供了对应的标签:
注入 list元素
下面给出参考代码。
集合类代码如下:
package com.sikiedu.bean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class MyCollection {
//数组
private Object[] array;
//list
private List list;
//set
private Set set;
//map
private Map map;
//properties
private Properties prop;
public Object[] getArray() {
return array;
}
public void setArray(Object[] array) {
this.array = array;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
@Override
public String toString() {
return "MyCollection [list="+list+",set="+set+",map=" + map + ", prop=" + prop + "]";
}
}
xml代码片段如下:
111
aaa
老李
25