第一个Spring程序
1. 软件版本
- JDK 1.8+
- Maven 3.5+
- IDEA 2018+
- SpringFramework 5.1.4+
官网开发文档https://docs.spring.io/spring/docs/current/spring-framework-reference/
2. 环境搭建
- Spring的jar包
maven中心仓库
https://mvnrepository.com/
pom.xml 导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
- Spring配置文件
配置文件放置的位置 - 任意,一般放置resources/文件夹下
配置文件的命名 applicationContext.xml
思考:日后应用Spring框架时,需要进行配置文件路径的设置。
Spring 的核心 API
Spring提供的 ApplicationContext 工厂
作用:用于对象的创建
好处:解藕合
ApplicationContext 是接口类型
1.接口:屏蔽实现的差异
2. 非web 环境: ClassPathAmlApplicationContext(main junit单元测试)
3. web环境:XmlWebApplicationContext
重量级资源- 占用内存多
- ApplicationContext工厂的对象占用大量内存
- 不会频繁的创建对.象,一个应用只会创建一个工厂对象.
- ApplicationContext 一定是线程安全的,
(并发访问 - 多线程访问 - 线程安全 - synchronize)
程序开发
1. 创建类型
2. 配置文件配置
id: 唯一性
class: 属性,全限定名
<bean id="person" class="com.gogogo.Person"></bean>
3. 通过工厂类 获得对象
//1. 获得Spring的工厂
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); //指定配置文件的路径
//2. 通过工厂类 获得对象
Person person = (Person) ctx.getBean("person");
4. 细节分析
Spring工厂创建对象
getBean()有多个重载函数
applicationContext.xml中配置如下
<bean id="person" class="com.gogogo.Person"></bean>
<bean id="person1" class="com.gogogo.Person"></bean>
<bean id="animal" class="com.gogogo.Animal"></bean>
getBean(Class aclass)
此时使用getBean(Person.class)时,会报异常,根据class 找到了两个对象,语法错误。
“expected single matching bean but found 2: person, person1”
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Person person = (Person) ctx.getBean(Person.class);
注意:若使用getBean(Person.class)这种承载,必须保证配置文件中只有一个该类型的bean标签。
getBean(String s, Class aclass)
使用getBean(“person”,Person.class)没问题,找到对应的id class 属性即可,不需要强制转换。
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Person person = ctx.getBean("person",Person.class);
getBeanDefinitionNames(),
返回值类型: 数组
获取的是Spring工厂配置文件中所有bean标签的id值
String[] ps= ctx.getBeanDefinitionNames();
for(String id : ps){
System.out.println("id = "+ id);
}
//output:
//id = person
//id = person1
//id = animal
getBeanNamesForType()
返回值类型: 数组
根据类型获得Spring配置文件中,所有该类型的id值。
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
String[] pts= ctx.getBeanNamesForType(Person.class);
for(String id : pts){
System.out.println("id = "+ id);
}
//ouput:
//id = person
//id = person1
containsBeanDefinition()
返回值类型: boolean
用于判断是否存在指定id的bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
if(ctx.containsBeanDefinition("person")){
System.out.println("Yes");
}else{
System.out.println("No");
}
//output
//Yes
containsBean()
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
if(ctx.containsBean("sd")){
System.out.println("Yes");
}else{
System.out.println("No");
}
//output
//No
- 配置文件中需要主要的细节
- 只配置class属性,没有id值
应用场景: 如果这个bean只需要使用一次,可以省去id,若多次使用,这需要配置id属性
//<bean id="person" class="com.gogogo.Person"></bean>
<bean class="com.gogogo.Person"></bean>
2. name属性
id大名,name小名,别名。
<bean id="person" name = "p" class="com.gogogo.Person"></bean>
可以通过name属性 获得和 id属性获得的一样的结果
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Person p = (Person) ctx.getBean("p");
System.out.println("p = "+p);
区别:
- 别名可以定义多个,但id属性只能有一个
<bean id="person" name = "p, p1, p2" class="com.gogogo.Person"></bean>
- xml的id属性值,命名是有要求的:必须以字母开头,后面可以跟字母,数字,下划线。不能以特殊字符开头。而别名没有要求。
name属性会应用在特殊命名场景下。
XML 现在没有限制,可以用反斜杠开头 - 代码区别,containsBean(), 可以判断id,也可以判断name。
containsBeanDefinition(), 只能判断id, 不能判断name值
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
//只能判断id
if(ctx.containsBeanDefinition("p")){
System.out.println("Yes");
}else{
System.out.println("No");
}
// id, name 都可以
if(ctx.containsBean("person")){
System.out.println("Yes");
}else{
System.out.println("No");
}
//output
//No
//Yes
Spring工厂底层实现的原理,简易版(无源码)
反射也会调用类的无参构造,也能调用私有函数
思考:
问题:未来的开发中,是不是所有的对象都交给Spring工厂来创建呢?
回答: 理论上是的,但是有特例,实体对象(entity)不会交给Spring创建,它是由持久层定义的,需要和数据库交互。
学习开心❤️
加油努力