Spring框架学习 -- 创建与使用

目录

[(1) 创建spring 项目](#(1) 创建spring 项目)

[① 创建maven项目](#① 创建maven项目)

②添加spring框架支持

[③ 添加启动项](#③ 添加启动项)

[(2) 创建 Bean对象](#(2) 创建 Bean对象)

[(3) 将Bean注入到容器](#(3) 将Bean注入到容器)

[(4) 获取Bean对象](#(4) 获取Bean对象)

[(5) 注意事项](#(5) 注意事项)

[(*) xml注入Bean对象id和name属性](#(*) xml注入Bean对象id和name属性)

[(6) Spring的创建和使用流程图](#(6) Spring的创建和使用流程图)


创作不易多多支持


(1) 创建spring 项目

首先我们使用的开发工具为idea 专业版.

想要创建一个spring项目, 首先需要使用到maven, 所以我们创建spring项目的方式和servelet类似, 可以总结为下面几个步骤:

  1. 创建一个maven项目
  2. 添加spring的框架支持
  3. 添加启动类

下面我们来依次分析这几个步骤

① 创建maven项目

这个想必大家都很熟, 如果不知道如何创建maven项目的可以参考我的其他文章.

②添加spring框架支持

首先我们需要在pom.xml文件里面添加两个依赖:

下面是两个依赖的代码:

XML 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
</dependencies>

从上述配置中可以看出,添加的框架有 spring-context:spring 上下⽂,还有 spring-beans:管理对象的模块.

接下来配置spring设置文件, 如下:

我们在resources目录中创建文件 springConfig.xml 文件, 然后往里面粘贴如下代码:

粘贴的代码如下:

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">
    
</beans>

然后刷新(reload)Maven项目:

如果下载速度慢的话, 是因为maven仓库在国外, 访问速度很慢, 这个时候就需要配置国内源, 具体如何配置国内源, 大体就是在maven的setting.xml文件中设置国内源镜像结点, 具体如何操作可以自行搜索.

③ 添加启动项

也就是添加主类, 这个和普通程序无异.

(2) 创建 Bean对象

只有先创建Bean对象, 才能把对象注入到容器中去, 首先我们应该学习如何创建Bean对象.

首先我们先创建一个User类如下:

java 复制代码
public class User {
    public void sayHi() {
        System.out.println("hello, how are you?");
    }
}

所谓的Bean对象, 其实就是java里面一个类的对象.

然后将Bean注入到容器

(3) 将Bean注入到容器

在我们配置好的springConfig.xml文件中的注入Bean, 如下:

下面我们来看看springConfig.xml的详细:

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="org.example.User"></bean>
</beans>

其中 一个<bean> 标签, 就代表一个bean对象, class是指的类的路径, 指明注入的是哪个类, id是这个类对象的名称, 方便于后面取出这个对象.

XML 复制代码
<beans>
 <bean id="user" class="org.example.User"></bean>
</beans>

(4) 获取Bean对象

获取Bean对象大致可以分为下面几步:

  • 得到spring的上下文支持, 因为对象都交给spring管理了, 所以要获取注入到spring容器中的类就需要得到spring的上下文
  • 通过spring的上下文对象, 获取到指定的Bean对象
  • 使用Bean对象

首先获取spring上下文:

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 创建BeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 创建读取器
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);

        // 加载配置文件
        reader.loadBeanDefinitions("springConfig.xml");

        // 获取Bean实例对象
        User user = (User)beanFactory.getBean("user");
        user.sayHi();
    }
}

这样子分为了四步, 对于记忆这方面也比较繁琐, 于是java将上面这三个步骤封装成一个步骤, 也就是下面的这个ApplicationContext类:

java 复制代码
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml")
                
    }
}

其中ApplicationContext就是spring的上下文类, ClassPathXmlApplicationContext是他的具体实现类. ClassPathXmlApplicationContext中的参数为我们配置好的spring配置文件名: springConfig.xml

除了ApplicationContext之外, 还可以使用BeanFactory类来获取spring上下文, 具体操作为:

java 复制代码
public class Main {
    public static void main(String[] args) {
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));

    }
}

ApplicationContext 和 BeanFactory 效果是⼀样的,ApplicationContext 属于 BeanFactory 的⼦类,

那么ApplicationContext和BeanFactory具体有什么区别? (这是一个常见的面试题)

  • 继承关系和功能方面来说: Spring容器有两个顶级的接口, 那就是BeanFactory 和ApplicationContext, 其中BeanFactory提供了基础访问容器的能力, 而ApplicationContext属于BeanFactory的子类, 它除了继承了BeanFactory的所有功能之外, 它还拥有其他独特的特性, 还添加了对国际化的支持, 资源访问支持, 以及事件传播等方面的支持
  • 从性能来说, ApplicationContext是一次性加载并初始化所有的Bean对象, 而BeanFactory是需要哪个才去加载哪个, 因此BeanFactory更加的轻量. 而ApplicationContext加载慢但是使用(这里的使用是指的取出Bean对象)非常的快速.

然后就是如何获取Bean对象了, spring的上下文对象中提供了一个getBean方法, 用来获取指定的对象, 他的参数为一个字符串, 用来指定一个Bean对象的id , 如下:

java 复制代码
// 1.得到 Spring 上下⽂对象
ApplicationContext context = new ClassPathXmlApplicationContext("springcon
fig.xml");
// 2.加载某个 bean
User user = (User) context.getBean("user");

此处我们再回过头来看看我们注入的类:

此处的路径为: org.example.User, springConfig.xml中的文件中注入的Bean如下:

XML 复制代码
        <bean id="user" class="org.example.User"></bean>

可以看出这个路径和对象是一一对应的.

获取到Bean之后, 使用Bean对象就可以像普通开发程序中那样使用类了:

java 复制代码
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));
        User user = (User)beanFactory.getBean("user");
        user.sayHi();

-- 输出:

需要注意的是, getBean方法返回的是Object类型, 因此使用的时候还需要强制类型转换, 将其转换为对应的类才可以使用, 或者是使用getBean的重载方法, 里面有两个参数, 一个是字符串对象, 代表要使用的Bean对象的id, 第二个参数是使用反射来获取这个对象所属的类:

java 复制代码
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));
        User user = beanFactory.getBean("user", User.class);
        user.sayHi();

此时getBean就会直接返回get的Bean对象的类型.

下面是其原码的定义 :

(5) 注意事项

spring配置文件的容器中注入的Bean对象的id要和getBean中的id一致:

除此之外, 我们在获取Bean对象的时候, 其实也可以直接传入一个Bean对应的类就可以将其取出来:

sping 配置文件如下:

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="org.example.User"></bean>
</beans>

main方法中来获取这个id为user的Bean对象, 但是我们getBean的时候只传入这个类, 而不是这个类的id名:

java 复制代码
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));
        User user = beanFactory.getBean(User.class);
        user.sayHi();

运行 -- 输出如下:

可以看出来, 可以成功取出Bean然后使用此Bean对象

但是我们思考一下, 任何情况下都能这样获取到Bean对象吗? 显然不是, 我们传入的是对应的Bean对象的类, 因此我们传入的是类名, 但是想想, 如果我们在spring容器中注入两个相同的类对象, 但是id不同, 再次使用传入类名的情况会成功吗?

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="user1" class="org.example.User"></bean>
        <bean id="user2" class="org.example.User"></bean>
</beans>

可以看到spring容器中已经被注入了两个Bean对象, 这两个Bean对象都属于User类, 我们再次去使用getBean(Class<T> var) 的方法去获取Bean对象

Bean对象获取:

java 复制代码
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));
        User user = beanFactory.getBean(User.class);
        user.sayHi();

-- 输出:

java 复制代码
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.example.User' available: expected single matching bean but found 2: user1,user2
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1180)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:416)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.example.Main.main(Main.java:12)

关键报错信息展示:

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.example.User' available: expected single matching bean but found 2: user1,user2

可以翻译一下就是:

可以看出找到了两个Bean对象: user1 和 user2, 但是spring不知道使用哪一个, 所以报错.

(*) xml注入Bean对象id和name属性

我们在注入一个Bean对象的时候, 如下:

XML 复制代码
        <bean id="userController" name="aaa,bbb,ccc" class="com.java.demo.Controller.UserController"></bean>

我们给这个Bean对象取了一个id, 然后又给了name属性设置了三个名字, 他们之间尊崇这样的原则:

  • 如果只有id, 那么这个Bean的name就为这个id里的内容
  • 如果只有name, 那么这个name属性的第一个值就为Bean的name.
  • 如果既有id又有name属性, 那么BeanName就为这个id, 同时你也可以通过别名来获取这个Bean对象.

解释, 这个name属性, 也就是 Bean的别名, 被维护在一个aliasMap的Map中. 也就是后面可以通过在这个map里面获取别名的形式来获取这个Bean对象.

(6) Spring的创建和使用流程图



相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J4 天前
从“Hello World“ 开始 C++
c语言·c++·学习