官网:https://spring.io/
Spring 是一个可以管理整合其他框架的框架
1. IOC 开发模式
程序不再负责对象的创建,而是直接使用ioc容器的对象来完成相关的业务逻辑
1.1 控制反转实现思想
1)Spring 根据配置文件 xml/注解,创建对象,并放到 ioc 容器(ConcurrentHashMap)里面,并且完成不同对象之间的依赖
2)当需要使用某个对象实例的时候,不需要再创建,直接从容器中获得
3)开发者更关注如何实现业务逻辑
注:
- DI - Dependency Injection 依赖注入,可以理解为IOC的另外一种叫法
- Spring 的最大价值就是通过配置给开发者提供需要使用的 web 对象(Servlet/Action/Controller, Service, Dao, JavaBean, entity)实现解耦
2. 快速入门
1.1 代码实现
先看一下代码结构
1)创建bean
package com.hspedu.spring.bean;
/**
* @author xlin
* @date 2024-01-12
* JavaBean
*/
public class Monster {
private Integer monsterId;
private String name;
private String skill;
public Monster(Integer monsterId, String name, String skill) {
this.monsterId = monsterId;
this.name = name;
this.skill = skill;
}
//无参构造器用于反射创建对象
public Monster() {
}
public Integer getMonsterId() {
return monsterId;
}
public void setMonsterId(Integer monsterId) {
this.monsterId = monsterId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
@Override
public String toString() {
return "Monster{" +
"monsterId=" + monsterId +
", name='" + name + '\'' +
", skill='" + skill + '\'' +
'}';
}
}
2)配置 xml 文件
<!--
1. 配置monster对象/javabean
2. 在beans中可以配置多个bean
3. bean表示就是一个java对象
4. class属性是用于指定类的全路径->spring底层使用反射创建
5. id属性表示该java对象在spring容器中的id, 通过id可以获取到对象
6. <property name="monsterId" value="100"> 用于给该对象的属性赋值,
如果没有给的话就是默认值
-->
<bean class = "com.hspedu.spring.bean.Monster" id="monster01">
<property name="monsterId" value="100"/>
<property name="name" value="牛魔王"/>
<property name="skill" value="芭蕉扇"/>
</bean>
3)test
@Test
public void getMonster() {
//1.创建容器,用接口来接收
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
//2.通过 getBean 获取对应的对象 默认返回的是Object,运行类型是 Monster
Monster monster01 = (Monster)ioc.getBean("monster01");
//3.输出
System.out.println(monster01.getClass());
System.out.println(monster01.getName());
System.out.println(monster01.getMonsterId());
//4.可以直接返回对应的class类型
Monster monster02 = ioc.getBean("monster01", Monster.class);
System.out.println(monster01 == monster02); //true 说明是同一个Monster对象
}
1.2 注意事项及细节
1)类加载路径
//验证类加载路径
@Test
public void classPath() {
File file = new File(this.getClass().getResource("/").getPath());
System.out.println(file); //D:\JavaCode\Spring_Study\out\production\Spring_Study
}
注意是在程序运行目录 out 下
2)Spring 容器结构/机制
ConcurrentHashMap 并没有存放对象的实例
在后面可以找到一个 propertyValues 的对象
这里的信息就是对应与在 xml 配置文件里的信息
beanDefinitionMap的table存的只是beans.xml配置文件的对象
创建出来的monster01放在接下来的singletonObjects中
getBean是怎么查到monster01的
- 首先,他会在beanDefinitionMap的table里找是否有monster01
- 如果发现有一个单例的对象,就又用monster01这个id去singletonObjects的table里获取真正的monster01。
- 如果发现不是单例的对象,他就通过反射机制动态创建一个单例的对象返回给ioc.getBean
3. 结构梳理
3.1 问题
1)注入 2 个 Monster 对象, 但是不指定 id
<bean class="com.hspedu.spring.beans.Monster" >
<property name="monsterId" value="1010"/>
<property name="name" value="牛魔王~"/>
<property name="skill" value="芭蕉扇~"/>
</bean>
<bean class="com.hspedu.spring.beans.Monster">
<property name="monsterId" value="666"/>
<property name="name" value="牛魔王~~!!"/>
<property name="skill" value="芭蕉扇~~"/>
</bean>
不会报错,会正常运行
系统会默认分配 id ,分配 id 的规则是 全类名#0 , 全类名#1 这样的规则来分配 id
就分配为
com.hspedu.spring.beans.Monster#0
com.hspedu.spring.beans.Monster#1