1.软件版本
下面这些是我本次进行第一个Spring程序所使用的环境
jdk 1.8
maven 3.5.7
idea 2021
SpringFramework 5.3.18
Spring框架的官网https://spring.io/
2.环境搭建
Spring的jar包
- 搜搜jar包的坐标网站https://mvnrepository.com/
- 设置pom.xml依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
Spring的环境配置文件
- 配置文件的存放位置:任意位置,只要在项目中就可以,没有硬性要求
- 配置文件的命名:没有硬性要求,可以随便取,建议:applicationContext.xml
- 既然配置文件放的位置和配置文件的名字都是随便的,那么Spring怎么知道我们把这些文件放在哪里。所以我们使用Spring框架的时候,需要进行配置文件路径的配置
3.Spring的核心API
- ApplicationContext
这是Spring为我们提供的工厂类,主要用于对象的创建
优点:解耦合
ApplicationContext接口类型
-
- 接口可以屏蔽实现的差异,哪一个类有接口的功能,就去实现这个接口
Spring提供两个接口的实现,用于不同的环境下面
- 非web环境(比如说main函数 或junit单元测试): ClassPathXmlApplicationContext
- web环境: XmlWebApplicationContext
- ApplicationContext是重量级资源(轻量级和重量级体现在对内存的占用上)
ApplicationContext工厂的对象会占用大量内存
不会频繁的创建对象,一个应用程序只会创建一个工厂对象(因为它占用内存多)
可能出现并发访问的情况,说明它是线程安全的,不然会出现并发问题
ApplicationContext工厂:一一定是线程安全的(允许多线程并发访问)
4.程序开发
①创建类型,我们想使用哪一个类,就创建对应的类
②配置文件的配置 applicationContext.xml
③通过工厂类来获得对象 ApplicationContext
④测试,如果使用单元测试的话,就得使用ClassPathXmlApplicationContext
@Test
public void test(){
//获得Spring的工厂 传入的参数是为了找到配置文件所在的位置
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
//通过工厂类来获得对象 传入的值是我们在配置文件写的id的值
Person person = (Person)ctx.getBean("person");
System.out.println("person="+person);
}
5.细节分析
Spring工厂创建的对象,叫做bean或者组件(componet)
getBean()方法是有重载方法的
5.1.相关方法说明
@Test
public void test2(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
//第一个参数是配置文件的id 第二个参数写的是我们想要创建的对象类型 这样就不用强转了
Person person = ctx.getBean("person", Person.class);
System.out.println(person);
}
getBeanDefinitionNames()是用来获取bean标签的id值
@Test
public void test3() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String names : beanDefinitionNames) {
System.out.println(names);
}
}
输出结果
person
person1
getBeanNamesForType()根据类型获取Spring配置文件中对应的id值
@Test
public void test4(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (int i=0;i<beanNamesForType.length;i++){
System.out.println(beanNamesForType[i]);
}
}
测试结果
person
person1
boolean containsBeanDefinition()用来判断是否存在指定id值的bean,不能用来判断name值
public void test4(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
//用来判断是否存在指定id值的bean
boolean c = ctx.containsBeanDefinition("person");
System.out.println(c);
}
containsBean()用来判断是否存在指定id值的bean,也可以判断name值
public void test4(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
//用来判断是否存在指定id值的bean
boolean person = ctx.containsBean("person");
System.out.println(person);
}
5.2.配置文件说明
5.2.1配置文件只配置class属性
Spring的配置文件中,bean标签没有加id属性也可以,可以只配置class属性
<bean class="com.zyh.basic.Person"></bean>
/**
* 用来测试Spring的配置文件
*/
@Test
public void test5(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
Person bean = ctx.getBean(Person.class);
System.out.println(bean);
}
我们来想一下,我们没有加上id属性,那么Spring会给我们提供默认的id值吗,有的
我们可以通过程序测试一下
getBeanDefinitionNames()这个方法可以获取配置文件的所有id值
@Test
public void test5(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
String[] beanNamesForType = ctx.getBeanDefinitionNames();
for (String name:beanNamesForType){
System.out.println(name);
}
}
输出结果
com.zyh.basic.Person#0
上面这种配置的应用场景
- 如果这个bean只需要使用一次,那么就可以省略id值
- 如果这个bean会使用多次,或者被其他bean引用则足以设置id值
5.2.2name属性和id属性的区别
作用:用在Spring的配置文件中,为bean对象定义别名
id的值相当于大名,name的值相当于小名,通过这两个,我们都可以获取对应的对象
<bean id="person" name="person2" class="com.zyh.basic.Person"></bean>
/**
* 用于测试name属性
*/
@Test
public void test6(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
Person person = (Person) ctx.getBean("person2");
System.out.println(person);
}
测试结果
com.zyh.basic.Person@4135c3b
我们来看看name属性和id属性的相同点和不同点
相同
ctx.getBean("id|name")--->Object
<bean id=" " class=" "
等效
<bean name=" "class=" "不同
- 别名可以定义多个, 但是id属性值只能有一个
以前的时候
- XML的id属性的值,命名要求:必须以字母开头,后面可以跟着字母,下划线,连字符(就是中划线-),不能以特殊字符开头,比如/person
- name属性的值,命名没有要求,可以设置成/person的形式
name属性会应用在特殊命名的场景下,比如/person
不过XML发展到了今天,ID属性的限制已经不存在了,我们也可以用/person
- 代码
用于判断是否存在指定id值的bean,不能判断name值
boolean c = ctx.containsBeanDefinition("person");
System.out.println(c);
用来判断是否存在指定id值的bean,也可以判断name值
boolean person = ctx.containsBean("person");
System.out.println(person);
6.Spring工厂的底层实现原理(初步认识)
Spring工厂是可以调用对象私有的构造方法来创建对象
7.思考
我们以后在开发过程中,是不是所有的对象都会交给Spring工厂来创建呢?
理论上是的。但是有特例:实体对象,实体对象是不交给Spring工厂来创建的,因为实体对象中是会封装操作数据库表中的数据,让Spring来创建这个对象的意义不大,因为我们需要的不仅仅是这个对象本身,而且还要这个实体类所对应的数据库中的数据,这些数据必须要操作数据库,我们是把这些对象交给持久层框架来创建的,比如Mybatis.
注意:上面我们的第一个Spring程序中的Person类,通过Spring工厂来创建对象只是为了快速掌握第一个Spring程序,以后开发中实体对象是交给持久层框架来创建的