Spring核心API分析
文章目录
1. Spring环境搭建
1.1 软件版本
- JDK1.8+
- Maven3.5+
- IDEA2018+
- SpringFramework 5.1.4
1.2 使用Maven导入依赖
访问Maven仓库官网获取依赖,将依赖配置复制到pom文件中。
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/springcontext -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
</dependencies>
2. 核心API分析
ApplicationContext
- 作用:是Spring提供的ApplicationContext工厂,用于对象的创建
- 优点:解耦合
ApplicationContext是一个接口类型
- 设计为接口类型的好处:屏蔽实现的差异
ApplicationContext接口的实现的两个主要实现:
- ⾮web环境 :
ClassPathXmlApplicationContext
(主要在main方法中使用,或者在Junit中使用) - web环境 :
XmlWebApplicationContext
ApplicationContext
是一个重量级资源
- ApplicationContext工厂的对象占用大量内存。
- 不会频繁的创建对象 : 一个应用只会创建⼀个工厂对象。
- ApplicationContext工厂:⼀定是线程安全的(多线程并发访问)
3. 程序开发
3.1 创建类型
package com.jc.bean;
public class User {
}
3.2 配置配置文件ApplicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="User" class="com.jc.bean.User"></bean>
</beans>
3.3 通过工厂类获得对象
使用单元的测试的方式,就用ClassPathXmlApplicationContext
来获取实例。
@Test
public void test1() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
User user = (User) ctx.getBean("User");
System.out.println(user);
}
控制台输出:
com.jc.bean.User@34c4973
4. 细节分析
4.1 名词分析
- Spring工厂创建的对象,叫做
bean
或者组件(componet
)
4.2 Spring工厂的相关的方法
- T getBean(String s, Class aClass) :
//通过这种⽅式获得对象,就不需要强制类型转换
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);
- T getBean(Class aClass) :
//当前Spring的配置⽂件中 只能有⼀个<bean class是Person类型
Person person = ctx.getBean(Person.class);
System.out.println("person = " + person);
- String[] getBeanDefinitionNames():
//获取的是 Spring⼯⼚配置⽂件中所有bean标签的id值
person person1 String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
- String[] getBeanNamesForType(@Nullable Class<?> aClass):
//根据类型获得Spring配置⽂件中对应的id值
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {
System.out.println("id = " + id);
}
- boolean containsBeanDefinition(String s):
//⽤于判断是否存在指定id值得bean
if (ctx.containsBeanDefinition("a")) {
System.out.println("true = " + true);
}else{
System.out.println("false = " + false);
}
- boolean containsBean(String s):
//⽤于判断是否存在指定id值得bean
if (ctx.containsBean("person")) {
System.out.println("true = " + true);
}else{
System.out.println("false = " + false);
}
4.3 配置文件中需要注意的细节
4.3.1只配置class属性
<bean class="com.jc.bean.Person"/>
-
上述这种配置 有没有id值?
答案是有的,Spring会为我们默认生成,如:
com.baizhiedu.basic.Person#0
-
应用场景: 如果这个bean只需要使用一次,那么就可以省略id值 如果这个bean会使用多次,或者被其他bean引用则需要设置id值
4.3.2 name属性
-
作用:用于在Spring的配置文件中,为bean对象定义别名
-
相同:通过
getBean()
方法获取对象用id
或者name
效果是一样的 -
区别:
- 别名可以定义多个,但是id属性只能有⼀个值
- XML的id属性的值,命名要求:必须以字母开头,字母数字 下划线 连字符不能以特殊字符开头如:/person,而name属性对命名没有要求
- XML发展到了今天:ID属性的限制,不存在 /person无法使用的情况了
-
代码
-
//⽤于判断是否存在指定id值得bean,不能判断name值 if (ctx.containsBeanDefinition("person")) { System.out.println("true = " + true); }else{ System.out.println("false = " + false); }
-
//⽤于判断是否存在指定id值得bean,也可以判断name值 if (ctx.containsBean("p")) { System.out.println("true = " + true); }else{ System.out.println("false = " + false); }
-
5. Spring工厂的原理简要分析
底层是使用反射的方法创建的对象,创建对象的过程需要用到类的构造器,如果构造器被私有化了,也会可以调用的,这是因为使用了反射的方式。
总之,Spring的工厂比我们写的工厂要高级的多,考虑到了很多的问题,灵活使用了Java反射的特性。
6. 思考
是不是所有的对象都交给Spring工厂来进行创建呢?
答:理论上是的,但是有特例。因为实际开发中,需要从数据库中获取数据,并且将数据封装到Bean对象中,这一部分的功能就要交给持久层框架来完成(持久层框架创建对象的过程也是通过反射来实现的)。