大家好 , 这个专栏给大家介绍一下 Java 家族的核心产品 - SSM 框架
Java 语言能走到现在 , 仍然屹立不衰的原因 , 有一部分就是因为 SSM 框架的存在
接下来 , 博主会带大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相关知识点
并且带领大家进行环境的配置 , 让大家真正用好框架、学懂框架
目标 :
在 Spring 里面 , 把对象叫做 Bean
我们接下来用 Maven 创建一个 Spring 项目
我们这里使用的环境是 IDEA 2021.2 社区版 , JDK 1.8
添加两个引用 :
这一步很简单 , 我们只需要把下面这段代码复制到 pom.xml 里面
当然也可以去中央仓库里面找
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.3.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>5.2.3.RELEASEversion>
dependency>
dependencies>
在这一步 , 我们一定要保证修改镜像源为国内的 , 要不然 超级大概率 会失败
我们还可以通过左侧来检验下载是否成功
我们点击上面的刷新按钮
但是我们下载的依赖只有 spring - content 和 spring - beans 啊 ? 这怎么多出来几个 ?
是这样的 , 我们的 spring - content 和 spring - beans 也是需要额外的依赖包的 , 如果单纯使用 spring - content 和 spring - beans , 也需要把它的几个依赖包导入进来 , 其实就相当于结婚的嫁妆
实际上就是添加 main 方法
那我们之前写 Servlet 程序 , 也没有 main 方法啊 ?
实际上 , Servlet 是隐藏 main 方法的 , 是不展示给用户的
我们这里的 Spring 程序就是一个最简单的程序 , 还是需要 main 方法的
在 java 目录底下新建一个类
存储 Bean 对象需要两步 :
public class User {
// 普通的类,普通的方法
public void sayHi() {
System.out.println("say hi!");
}
}
在 Spring 里面 , 并不是所有的 Bean 都会被存储到 Spring 里面 , 只有需要的才会存储到 Spring 里面
而这个存储 , 也不是真正意义上的存储 , 只是告诉 Spring , 这个 Bean 需要托管给 Spring
那么我们接下来需要在 resources 里面新建一个文件 , 叫做 spring-config.xml (这个名字大家也可以起别的 , 这里推荐大家起这个就行)
然后把这段代码复制进去
<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">
beans>
目前的只是准备工作 , 我们接下来才是将 Bean 存储到 Spring 的核心操作
<?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">
<!-- 注册一个对象到 Spring 中 -->
<!-- 先写一个 bean 标签 -->
<bean id="user" class="User"></bean>
</beans>
里面的 class 也是需要写包名的 , 但是因为我们没创建包 , 所以就没写
那么我们可以改一下 , 把代码放到包里面
目前为止 , 我们只是声明存储对象到 Spring 里面了 , 并不是真正存储到 Spring 里面了 , 正常情况下 , 我们的 Spring 是懒加载 , 在启动 Spring 的时候 , 他并不会立即存储 Spring 对象 , 但是从广义上来理解 , 我们的 Spring 已经存储这个对象了
对象都交给 Spring 管理了,所以获取对象要从 Spring 中获取,那么就得先得到 Spring 的上下文。
Spring 上下文对象可使用 ApplicationContext
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
}
}
先不管选哪个 , 我们注意 : getBean 返回值是 Object , 但是我们的对象是 User 类型 , 所以我们需要强转一下
import com.ethan.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2. 从 Spring 里面获取对象
// User user = new User();//在当前类当中创建 User 对象,原始方式不推荐[存在代码耦合]
User user = (User)context.getBean("user");//只有第一次执行,才会创建.因为是单例模式,创建过后会一直留着,下次用直接拿走
}
}
import com.ethan.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2. 从 Spring 里面获取对象
// User user = new User();//在当前类当中创建 User 对象,原始方式不推荐[存在代码耦合]
User user = (User)context.getBean("user");//只有第一次执行,才会创建.因为是单例模式,创建过后会一直留着,下次用直接拿走
// 3. 使用 bean
user.sayHi();//跟以前一样
}
}
我们之前说 resources 目录底下的配置文件推荐大家使用 spring-config.xml
那么这个名字其实叫什么都行
那我们改成 spring 看看还能不能成功
成功了
但是这种虽然合法但是不规范
那我们试一下这种情况 :
配置文件名称叫 spring-config.xml , 我们的代码里面写成了 spring.xml
那么运行一下 , 看看会不会运行起来
那么我们帮大家排查一下错误
那么就是 spring.xml 没有找到
因为我们的配置文件叫 spring-config.xml , 不是 spring.xml , 所以就会报错
而且下面还有行数提醒
getBean(String s)
我们之前介绍的方法 :getBean(String s)
: 根据名称来获取 bean 对象
这种方法需要进行强转 , 但是他有一个好处 : 我们注册多个 bean , 他会精准定位
比如 :
那么我们的这种方法能正常识别吗 ?
那么这种情况还是挺常见的 : 在公司协同开发 , 张三使用了 user , 李四不知道 , 李四也使用了 user , 这样就产生了重复
原则上来说 , 一个 key 只能出现一次 , 我们就可以把这个第二个 user 改成 user2
那有的人就问了 , 怎么证明 User 和 User2 是不一样的呢 ? 因为他们打印的结果相同啊 , 就会有人以为他们是不是一个东西起了两个名字啊 , 那很好证明
那么我们还可以去证明 user 是不是单例模式
为 true 就代表是单例模式 , 因为 Spring 中创建出一个对象就会一直存储到 Spring 中 , 方便后续使用 , 就不用再去重新创建了
getBean(class aclass)
getBean(class
: 根据类型获取 bean 对象
import com.ethan.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2. 从 Spring 里面获取对象
// 2.1 根据一个 String 参数获取 bean
//User user = (User)context.getBean("user");//只有第一次执行,才会创建.因为是单例模式,创建过后会一直留着,下次用直接拿走
// 2.2 根据一个 Class 参数获取 bean
User user = context.getBean(User.class);//这种方法不用强转了
// 3. 使用 bean
user.sayHi();//跟以前一样
}
}
这种情况是 spring-config.xml 里面只有一个 bean 对象
那么有两个呢 ?
再运行一下 :
看一下异常
我们再看一下 spring-config.xml
import com.ethan.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2. 从 Spring 里面获取对象
// 2.1 根据一个 String 参数获取 bean
/*User user = (User)context.getBean("user");
User user1 = (User)context.getBean("user");
User user2 = (User)context.getBean("user2");
System.out.println("user:" + user);
System.out.println("user1:" + user1);
System.out.println("user2:" + user2);
System.out.println("user == user1 -> " + (user == user1));
System.out.println("user == user2 -> " + (user == user2));//为true说明他们地址相同,是一个对象;为false说明地址不同,不是同一个对象*/
// 2.2 根据一个 Class 参数获取 bean
User user = context.getBean(User.class);//这种方法不用强转了
// 3. 使用 bean
user.sayHi();//跟以前一样
}
}
getBean(String s , class aclass)
getBean(String s , class
: 这种方法更加稳健 , 虽然他比第一种也没差哪去 , 不过如果是第一种方法 , 万一内容为 null , 对 null 进行强转就会出现问题 , 但是你通过这种方法的话 , 整体就会返回一个 null , 就不存在空指针问题了
import com.ethan.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 得到 Spring 上下文对象
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2. 从 Spring 里面获取对象
// 2.1 根据一个 String 参数获取 bean
/*User user = (User)context.getBean("user");
User user1 = (User)context.getBean("user");
User user2 = (User)context.getBean("user2");
System.out.println("user:" + user);
System.out.println("user1:" + user1);
System.out.println("user2:" + user2);
System.out.println("user == user1 -> " + (user == user1));
System.out.println("user == user2 -> " + (user == user2));//为true说明他们地址相同,是一个对象;为false说明地址不同,不是同一个对象*/
// 2.2 根据一个 Class 参数获取 bean
//User user = context.getBean(User.class);//这种方法不用强转了
// 2.3 根据 String(bean id) 和 Class 参数获取 bean
User user = context.getBean("user",User.class);//更加的稳健
// 3. 使用 bean
user.sayHi();//跟以前一样
}
}
Spring 上下文对象可使用 ApplicationContext , 我们还可以使用 BeanFactory (ApplicationContext的父类) 来作为 Spring 的上下文
不过 IDEA 已经不推荐我们使用这种方法了
import com.ethan.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class App {
public static void main(String[] args) {
// 1. 获取上下文对象
BeanFactory context = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
// 2. 从 Spring 里面获取对象
User user = context.getBean("user2", User.class);
// 3. 使用方法
user.sayHi();
}
}
运行一下 :
那么既然他们都能运行成功 , 那有什么区别呢 ?