Spring ApplicationContext 容器
1. 介绍¶
Application Context 是 BeanFactory 的子接口,也被成为 Spring 上下文。 Application Context
是spring中较高级的容器。和BeanFactory类似,它可以加载配置文件中定义的bean,将所有的bean集中在一起,当有请求的时候分配bean。另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器。这个容器在 org.springframework.context.ApplicationContext interface
接口中定义。
ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactory,ApplicationContext 会更加优秀。当然,BeanFactory 仍可以在轻量级应用中使用,比如移动设备或者基于 applet 的应用程序。
最常被使用的 ApplicationContext 接口实现:
FileSystemXmlApplicationContext
:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。ClassPathXmlApplicationContext
:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。WebXmlApplicationContext
:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
案例¶
创建spring项目。选择maven模式。
Person.class
package com.cmz.bean; import java.util.Date; /** * @author summer * @create 2020-02-28 18:43 */ public class Person { private int id; private String name; private Integer age; private String gender; private Date date; public Person() { } public Person(int id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } public Person(int id, Integer age, String gender) { this.id = id; this.age = age; this.gender = gender; } public Person(int id, String name, Integer age, String gender, Date date) { this.id = id; this.name = name; this.age = age; this.gender = gender; this.date = date; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + ", date=" + date + '}'; } }
Address.class
package com.cmz.bean; /** * @author summer * @create 2020-02-28 18:24 */ public class Address { private String province; private String city; private String town; public Address() { System.out.println("Address 被创建"); } public Address(String province, String city, String town) { this.province = province; this.city = city; this.town = town; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getTown() { return town; } public void setTown(String town) { this.town = town; } @Override public String toString() { return "Address{" + "province='" + province + '\'' + ", city='" + city + '\'' + ", town='" + town + '\'' + '}'; } }
ioc.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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--<bean id="person" class="com.cmz.bean.Person" scope="prototype">--> <!--根据属性值设置的时候,name的名字取决于set方法后面的参数首字母小写的名称--> <!-- name: 表示参数列表的名称 value: 表示实际的具体指 type: 表示值的类型 index: 表示值的下标,从0开始 --> <bean id="person" class="com.cmz.bean.Person"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="20"></property> <property name="gender" value="男"></property> <property name="date" value="2020/02/28"></property> </bean> <!--使用构造器的方法赋值的生活,参数的name属性是由构造方法的参数名称决定的--> <bean id="person2" class="com.cmz.bean.Person"> <constructor-arg name="id" value="2"></constructor-arg> <constructor-arg name="name" value="可可"></constructor-arg> <constructor-arg name="age" value="18"></constructor-arg> <constructor-arg name="gender" value="女"></constructor-arg> <constructor-arg name="date" value="2020/02/28"></constructor-arg> </bean> <!--使用构造器的方法赋值的生活,可以吧name的属性值不写,但是要注意 必须要保证数值跟构造器的参数列表的顺序一致--> <bean id="person3" class="com.cmz.bean.Person"> <constructor-arg value="3"></constructor-arg> <constructor-arg value="多多"></constructor-arg> <constructor-arg value="18"></constructor-arg> <constructor-arg value="女"></constructor-arg> <constructor-arg name="date" value="2020/02/28"></constructor-arg> </bean> <!--使用构造器的方法赋值的生活,可以吧name的属性值不写,但是要注意 必须要保证数值跟构造器的参数列表的顺序一致,若是不一致的话 ,可以通过index的下标方式来标注,从0开始 --> <bean id="person4" class="com.cmz.bean.Person"> <constructor-arg value="3"></constructor-arg> <constructor-arg value="女" index="3"></constructor-arg> <constructor-arg value="18"></constructor-arg> <constructor-arg value="嘻嘻" index="1"></constructor-arg> <constructor-arg name="date" value="2020/02/28"></constructor-arg> </bean> <bean id="person5" class="com.cmz.bean.Person"> <constructor-arg value="3"></constructor-arg> <constructor-arg value="18" index="2"></constructor-arg> <constructor-arg value="嘻嘻" index="1"></constructor-arg> <constructor-arg value="女" index="3"></constructor-arg> <constructor-arg name="date" value="2020/02/28"></constructor-arg> </bean> <!--当有多个相同参数的构造方法存在的时候,默认情况下是覆盖的过程,后面的构造方式会覆盖前面的构造方法 如果非要赋值给另一个构造方法的话,可以使用type的参数来执行指定 --> <bean id="person6" class="com.cmz.bean.Person"> <constructor-arg value="3"></constructor-arg> <constructor-arg value="多多"></constructor-arg> <constructor-arg value="18"></constructor-arg> </bean> <bean id="person7" class="com.cmz.bean.Person"> <constructor-arg value="3"></constructor-arg> <constructor-arg value="多多"></constructor-arg> <constructor-arg value="18" type="java.lang.Integer"></constructor-arg> </bean> <!--总结: 在日常工作中,一般多用哪个name,value,其他很少用--> <!--命名空间--> <bean id="person8" class="com.cmz.bean.Person" p:id="5" p:name="王五" p:age="25" p:gender="男" p:date="2020/02/28"></bean> </beans>
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cmz</groupId> <artifactId>spring_study</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.3.RELEASE</version> </dependency> </dependencies> </project>
MyTest.class
import com.cmz.bean.Person; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author summer * @create 2020-02-22 21:06 */ public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml"); // 根据bean标签id来获取对象 Person person = context.getBean("person", Person.class); Person person1 = context.getBean("person", Person.class); System.out.println(person); System.out.println(person==person1); /* * 根据bean的类型来获取对象 * 注意: 当通过类型进程获取的时候,如果存在两个相同的类型对象, * 此时将无法完成获取工作 * */ // Person bean = context.getBean(Person.class); // System.out.println(bean); ApplicationContext context2 = new ClassPathXmlApplicationContext("ioc.xml"); Person person2 = context2.getBean("person2", Person.class); System.out.println(person2); ApplicationContext context3 = new ClassPathXmlApplicationContext("ioc.xml"); Person person3 = context3.getBean("person3", Person.class); System.out.println(person3); ApplicationContext context4 = new ClassPathXmlApplicationContext("ioc.xml"); Person person4 = context4.getBean("person4", Person.class); System.out.println(person4); ApplicationContext context5 = new ClassPathXmlApplicationContext("ioc.xml"); Person person5 = context5.getBean("person5", Person.class); System.out.println(person5); ApplicationContext context6 = new ClassPathXmlApplicationContext("ioc.xml"); Person person6 = context6.getBean("person6", Person.class); System.out.println(person6); ApplicationContext context7 = new ClassPathXmlApplicationContext("ioc.xml"); Person person7 = context7.getBean("person7", Person.class); System.out.println(person7); //命名空间 ApplicationContext context8 = new ClassPathXmlApplicationContext("ioc.xml"); Person person8 = context8.getBean("person8", Person.class); System.out.println(person8); Person person9 = new Person(); System.out.println(person9); } }
运行结果
Person{id=1, name='张三', age=20, gender='男', date=Fri Feb 28 00:00:00 CST 2020} true Person{id=2, name='可可', age=18, gender='女', date=Fri Feb 28 00:00:00 CST 2020} Person{id=3, name='多多', age=18, gender='女', date=Fri Feb 28 00:00:00 CST 2020} Person{id=3, name='嘻嘻', age=18, gender='女', date=Fri Feb 28 00:00:00 CST 2020} Person{id=3, name='嘻嘻', age=18, gender='女', date=Fri Feb 28 00:00:00 CST 2020} Person{id=3, name='多多', age=18, gender='null', date=null} Person{id=3, name='null', age=18, gender='多多', date=null} Person{id=5, name='王五', age=25, gender='男', date=Fri Feb 28 00:00:00 CST 2020} Person{id=0, name='null', age=null, gender='null', date=null}
注意
1. ClassPathXmlApplicationContext 是读取 src 目录下的配置文件 2. FileSystemXmlApplicationContext 即系统文件路径,文件的目录。 (注意:如果你的xml文件放在WEB-INF文件夹下,需要用这个,否则会找不到该文件) 第一步生成工厂对象。加载完指定路径下 bean 配置文件后, 利用框架提供的 ClassPathXmlApplicationContext API 去生成工厂 bean。 ClassPathXmlApplicationContext 负责生成和初始化所有的对象, 比如,所有在 XML bean 配置文件中的 bean。 第二步利用第一步生成的上下文中的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象。一旦得到这个对象, 就可以利用这个对象来调用任何方法。
以上先看着大概,接下来会慢慢解释。都是以这个例子讲解。