从0学会Spring框架

文章目录

  • 1. 对Spring的理解
  • 2. Spring IoC
  • 3. DI
  • 4. 如何创建一个Spring项目
    • 4.1 创建一个Maven项目
    • 4.2 添加Spring框架支持
    • 4.3 添加启动类
  • 5. 存储Bean对象
    • 5.1 添加配置文件
    • 5.2 创建Bean对象
    • 5.3 注册Bean
  • 6. 获取并使用Bean对象
  • 7. 更简单存储Bean对象的方式
    • 7.1 前置工作
    • 7.2 添加存储对象的注解
      • 7.2.1 类注解
      • 7.2.2 方法注解
  • 8. 对象装配/对象注入
    • 8.1 属性注入
    • 8.2 构造方法注入
    • 8.3 Setter注入
    • 8.4 @Resource注解
    • 8.5 @Bean将一个对象多次注入问题

1. 对Spring的理解

Spring是一个框架,包含了众多工具方法的IoC容器

什么是容器?

容器就是容纳物品的装置,比如:

  • List/Map,用来储存数据,说明它是一个数据存储容器
  • Tomcat,webapps目录下保存多个web应用程序,说明它是一个web容器

什么是IoC?

IoC的意思就是控制反转,是一种思想,主要通过IoC容器实现控制权发生反转,如对象的初始化及依赖关系(对象引用另一个对象),由程序自己控制这部分逻辑转变为由容器统一控制

在传统的开发中,如果A对象依赖B对象,那在A对象中就要new B对象,此时B对象的控制权就在A中,但是如果B对象一旦有所改变,如构造方法改变,那在A中也就要发生改变

控制反转呢就是控制权发生反转,B对象的控制权交给容器统一管理,此时B对象改变的话,A对象不用做任何处理,容器自动的将改动后的B对象交给A,此时A不必关注B的实现的方式,只管用就行

IoC的优点: 实现代码的解耦,将对象的生命周期交给IoC容器来管理,程序员无需管理

2. Spring IoC

前面说了Spring是一个包含众多工具方法的IoC容器,所以关键还是在容器上,所谓容器,就得具有容器的基本功能,取东西,存东西,对应这里的Spring容器,它具有最基本的功能为:

  • 将对象存储到容器
  • 从容器中将对象取出

Spring IoC就是一个实现了IoC思想的框架,具有存储Bean和取Bean的功能

将容器中存储的对象称为Bean对象(Java中的普通对象),Spring是一个IoC容器也就是将对象的创建和销毁的权利都交给Spring来管理,它本身具备了存储对象和获取对象的能力

3. DI

DI的意思为依赖注入,就是由IoC容器在运行期间,动态的将某种依赖关系注入到当前类中,就是将依赖的某个对象拿过来给当前类使用

DI与IoC的区别?

IoC是一种思想,DI为具体实现,它俩是从不同角度描述同一件事情,就是利用IoC容器,利用依赖关系注入的方式实现对象之间的解耦,例如:吃饭(IoC),吃米饭(DI)

4. 如何创建一个Spring项目

4.1 创建一个Maven项目

创建Maven项目
设置好创建项目的路径

设置路径

4.2 添加Spring框架支持

在pom.xml中添加Spring的框架支持,xml配置如下:

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.23</version>
        </dependency>
    </dependencies>

4.3 添加启动类

在java文件夹下,创建一个启动类,包含main方法

启动类

5. 存储Bean对象

5.1 添加配置文件

第一次添加需要在项目中添加Spring配置文件(只需第一次添加

resources目录下创建一个spring-config.xml(此文件名可以为别的,建议为spring-config)

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>

5.2 创建Bean对象

Bean对象就是Java中普通的对象,这里我们创建一个Dog类

public class Dog {
    public void say(String name){
        System.out.println(name+":旺旺~");
    }
}

5.3 注册Bean

将创建好的Bean对象通过配置文件注册到Spring中

<bean id="dog" class="com.beans.Dog"></bean>

id为bean的名称,相当于给bean对象起一个名字,class为bean的路径(包名+类名)

6. 获取并使用Bean对象

使用Spring上下文的方式获取Bean对象

  1. 先获取Spring上下文
  2. 再通过上下文对象提供的方法获取指定的Bean对象
public class App {
    public static void main(String[] args) {
    //ApplicationContext是一个接口,new其实现类,构造方法的参数为刚才创建的配置文件的名称
    //得到spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //使用spring容器获取bean对象,这里使用bean的名称获取,就是配置文件中bean的id
        //getBean的返回类型为Object,所以强转一下
        Dog dog = (Dog)context.getBean("dog"); //该句代码就是上述说的DI
        dog.say("旺财");
    }
}

打印结果

getBean的更多用法:

  • 使用bean id获取bean(需强转,返回类型为Object,id必须唯一
Dog dog = (Dog)context.getBean("dog");
  • 使用bean class获取bean(该类必须有唯一的bean,也就是多个该类型被注入到Spring中会报错)
Dog dog = context.getBean(Dog.class);

使用此种方式不用强转,但是该类必须唯一

  • 使用bean id和class获取bean
Dog dog = context.getBean("dog",Dog.class);

此种方式是为了解决使用class获取bean时存在多个相同类型的bean对象,此时加上id(因为id的唯一性)就可以获取唯一的bean对象,当相同的类多次注入到spring容器中时,此时多个相同类型的bean对象各不相同(每个bean都有其唯一的地址)

不管使用哪种方式获取,都必须保证能获取唯一的bean对象,否则会报错

推荐使用最后一种id和class获取bean对象

使用Bean工厂的方式获取Bean对象

  1. 先获取bean工厂对象
  2. 再使用该对象的getBean方法获取Bean对象
public class App {
    public static void main(String[] args) {
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        Dog dog = factory.getBean("dog",Dog.class);
        dog.say("旺财");
    }
}

打印结果

ApplicationContext与BeanFactory有什么区别?

  • ApplicationContext属于BeanFactory的子类
  • BeanFactory只提供了基础访问Bean的方法,而ApplicationContext除了拥有BeanFactory的所有功能外,还提供了更多的方法实现,如对国际化的支持,资源访问的支持以及事件和传播等方面的支持
  • 性能两者不同,BeanFactory是按需加载Bean类似懒加载,而ApplicationContext在创建时会将所有Bean加载起来,属于饿汉式

在这里插入图片描述

使用ApplicationContext的方式,当代码执行完上述步骤的时候,所有的bean对象都会被初始化好加载到spring容器中

在这里插入图片描述

使用BeanFactory的方式,只有真正调用getBean的时候才会初始化对应的对象然后加载到spring容器中,类似懒加载的方式

7. 更简单存储Bean对象的方式

7.1 前置工作

更简单存储Bean的方式就是使用包扫描+注解的方式,此种方法可以和上述添加bean标签的方式共存

在Spring配置文件中设置bean扫描路径,将前面配置的xml文件换成下面的,但是注意下面存放bean对象的包名要和自己的创建的bean对象的包名要对应

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--    com.beans 是所有要存放bean对象的根路径-->
    <content:component-scan base-package="com.beans"></content:component-scan>
</beans>

7.2 添加存储对象的注解

7.2.1 类注解

  • @Controller,控制层(前端参数校验)
  • @Service,服务层(数据组装和接口调用)
  • @Repository,数据持久层(负责和数据库进行交互)
  • @Component,组件(非其他四类)
  • @Configuration,配置层(系统运行前,提前加载一些资源)
@Controller
public class UserController {
    public void sayHello(){
        System.out.println("hello Controller");
    }
}

使用注解注入Bean对象时,bean的名称也就是bean id为类名小驼峰的表示
如果原类名的第一个字母和第二个字母都是大写,那么此时的bean id为原类名不变

public class Application1 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //bean id为类名改写为小驼峰方式
        UserController userController = context.getBean("userController",UserController.class);
        userController.sayHello();
    }
}

结果

其他四个注解与此用法相同

为什么需要五大类注解

五大类注解
提高代码的可读性,让程序员能够直观的判断当前类的用途

类注解的关系

@Controller,@Service,@Repository,@Configuration都是基于@Component实现的,所以可以认为@Component是它们的父类

7.2.2 方法注解

@Bean注解加到方法上,将方法的返回值添加到容器中

注意: @Bean注解必须结合五大类注解来使用,并且方法必须有返回值

@Component
public class Students {
    @Bean
    public Student s1(){
        Student student = new Student();
        student.setName("张三");
        student.setAge(23);
        return student;
    }
}
public class App1 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        Student student = context.getBean("s1",Student.class);
        System.out.println(student);
    }
}

打印结果

@Bean重命名

@Bean命名规则:

  • 当没有设置name属性时,方法名为bean名称
  • 当设置了name属性,只能通过name属性对应的值来获取,使用方法名就获取不到
@Component
public class Students {
    @Bean(name = "student1")
    public Student s1(){
        Student student = new Student();
        student.setName("张三");
        student.setAge(23);
        return student;
    }
}
public class App1 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        Student student = context.getBean("student1",Student.class);
        System.out.println(student);
    }
}

打印结果

起名字的时候,可以起多个名字:

    @Bean(name = {"user1","user2","user3"})
    public User getUser(){
        User user = new User();
        user.setUsername("张三");
        user.setAge(10);
        return user;
    }

8. 对象装配/对象注入

8.1 属性注入

使用@Autowired注解获取到Spring中的Student对象,将其注入到UserController1的属性中

@Controller
public class UserController1 {

    @Autowired
    private Student student;

    public void sayHello(){
        System.out.println(student);
    }
}
public class App2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController1 userController1 = context.getBean(UserController1.class);
        userController1.sayHello();
    }
}

打印结果

8.2 构造方法注入

构造方法注入是在构造方法上加@Autowired,实现注入

@Service
public class UserService {

    private Student student;

    @Autowired
    public UserService(Student student1){
        this.student = student1;
    }
    public void say(){
        System.out.println(student);
    }
}
public class App2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService = context.getBean(UserService.class);
        userService.say();
    }
}

打印结果

如果当前类中只存在一个构造方法,那么@Autowired可以省略,多个构造方法时则不可以省略

8.3 Setter注入

Setter注入是在设置的set方法上加@Autowired注解

@Controller
public class UserController2 {
    private Student student;

    @Autowired
    public void setStudent(Student student) {
        this.student = student;
    }

    public void say(){
        System.out.println(student);
    }
}
public class App1 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController2 userController2 = context.getBean(UserController2.class);
        userController2.say();
    }
}

注意: 属性注入与Setter注入不可往final修饰的变量中注入,但是构造方法注入可以往final修饰的变量中注入

原因:final修饰的变量必须直接赋值,或者使用构造方法赋值,构造方法只会执行一次

8.4 @Resource注解

在进行对象注入的时候,除了可以使用 @Autowired 关键字之外,我们还可以使用 @Resource 进行注入

public class UserService2 {
    @Resource(name = "student1")
    private Student student;
    
    public void say(){
        System.out.println(student);
    }
}

@Autowired与@Resource区别

  1. 出身不同:@Resource来自于jdk,@Autowired时Spring框架提供的
  2. 用法不同:@Autowried可以用于属性注入,构造方法注入,Setter注入,@Resource不支持构造方法注入
  3. 参数不同:@Resource支持更多的参数设置,比如name,type,而@Autowried只支持required参数

8.5 @Bean将一个对象多次注入问题

在spring容器中找bean有两种方式:

  1. 根据bean的名称也就是bean id
  2. 根据bean的类型也就是bean class

先创建一个Cat类,属性有name和color,并提供get,set,toString方法

往Spring中注入多个Cat对象

@Controller
public class Cats {
    @Bean
    public Cat cat1(){
        Cat cat = new Cat();
        cat.setName("糯米");
        cat.setColor("白色");
        return cat;
    }
    
    @Bean
    public Cat cat2(){
        Cat cat = new Cat();
        cat.setName("汤圆");
        cat.setColor("黑色");
        return cat;
    }
}

在另一个类中获取Cat对象

@Controller
public class CatController {

    @Autowired
    private Cat cat;

    public void getCat(){
        System.out.println(cat);
    }
}

创建启动类

public class App3 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        CatController catController = context.getBean(CatController.class);
        catController.getCat();
    }
}

报错

发现报错了,因为Spring中已经注入了两个Cat对象,所以此时不知道获取哪个对象

在这里插入图片描述

三种解决方案

  1. 精确的描述bean的名称(将注入的名称写对)
  2. 使用@Rsource设置name方式来重命名注入对象
  3. 使用@Autowired+@Qualifier来筛选bean对象

方案一:精确的描述bean的名称(将注入的名称写对)

@Controller
public class CatController {

    @Autowired
    private Cat cat1; //精确描述bean名称

    public void getCat(){
        System.out.println(cat1);
    }
}

方案1

方案二: 使用@Rsource设置name方式来重命名注入对象

@Controller
public class CatController {

    @Resource(name = "cat2")
    private Cat cat;

    public void getCat(){
        System.out.println(cat);
    }
}

结果

方案三:使用@Autowired+@Qualifier来筛选bean对象

@Controller
public class CatController {

    @Autowired
    @Qualifier(value = "cat1")
    private Cat cat;

    public void getCat(){
        System.out.println(cat);
    }
}

结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/17353.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于javaweb的学生就业管理系统

一、简介 学生基业管理系统有三个角色&#xff1a;管理员、企业、学生 对学生信息管理、企业信息管理、求职信息管理 后端架构&#xff1a;spring springmvc mybatis 前端架构&#xff1a;jsp layui 系统环境&#xff1a;jdk1.8 | maven | mysql 二、主要功能 1. 登录…

一个集团企业,如何从0到1构建信息化系统?

当今时代&#xff0c;信息技术已经成为企业发展不可或缺的一部分&#xff0c;特别是对于一个大型集团公司来说&#xff0c;如何构建一个高效的信息化系统对于其业务发展至关重要。 我们想要构建一个优质高效的信息化系统&#xff0c;首先需要了解现在大的趋势是怎样的。 目前…

看我如何通过帮助服务台轻松黑掉数百家公司

导语&#xff1a;几个月前&#xff0c;我发现黑客可以利用一个漏洞访问目标公司的内部通信。 这个漏洞只需要点击几下&#xff0c;就可以访问企业内部网络、 Twitter等社交媒体账户&#xff0c;以及最常见的Yammer和Slack团队。 更新: The Next Web 写了一篇我发现的这个漏洞的…

【Java笔试强训 28】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;猴子分桃…

二分法相关使用

文章目录 1. 在一个有序数组中,找某个数是否存在2. 在一个有序数组中,找大于等于某个数最左侧的位置3. 在一个有序数组中, 找小于等于某个数最右侧的位置4. 局部最大值问题 1. 在一个有序数组中,找某个数是否存在 在线OJ&#xff1a;704. 二分查找 有序数组下的二分思路如下:…

几种常见时间复杂度实例分析

多项式量级 常量阶 O(1) 对数阶 O(logn) 线性阶 O(n) 线性对数阶 O(nlogn) 平方阶O(n2 ),立方阶O(n3 )...k次方阶O(nk) 非多项式量级&#xff08;NP&#xff08;Non-Deterministic Polynomial&#xff0c;非确定多项式&#xff09;问题&#xff09; 指数阶O(2n) 阶乘阶…

Android WebRtc+SRS/ZLM视频通话(1):虚拟机安装Ubuntu

Android WebRtcSRS/ZLM视频通话&#xff08;1&#xff09;&#xff1a;虚拟机安装Ubuntu 来自奔三人员的焦虑日志 秉着没事找事的原则&#xff0c;这里直接从服务器安装开始说起&#xff0c;也当记录自己这一路以来的愚昧之举&#xff0c;由于没有物理服务器&#xff0c;这里以…

MySQL 精选 35 道面试题大厂稳了(含答案)

MySQL 精选 35 道面试题 1.说一下 MySQL 执行一条查询语句的内部执行过程&#xff1f;2.MySQL 查询缓存有什么优缺点&#xff1f;3.MySQL 的常用引擎都有哪些&#xff1f;4.常用的存储引擎 InnoDB 和 MyISAM 有什么区别&#xff1f;5.什么叫回表查询&#xff1f;6.如果把一个 I…

95后阿里P7晒出工资单:狠补了这个,真香···

最近一哥们跟我聊天装逼&#xff0c;说他最近从阿里跳槽了&#xff0c;我问他跳出来拿了多少&#xff1f;哥们表示很得意&#xff0c;说跳槽到新公司一个月后发了工资&#xff0c;月入5万多&#xff0c;表示很满足&#xff01;这样的高薪资着实让人羡慕&#xff0c;我猜这是税后…

TCP的粘包和拆包

UDP有数据边界&#xff0c;TCP是没有数据边界&#xff0c;是流协议。如何拆包&#xff0c;就要靠应用层来处理。 四层网络模型&#xff0c;消息在进入每一层时都会多加一个报头。mac头部记录的是硬件的唯一地址&#xff0c;IP头记录的是从哪来和到哪去&#xff0c;传输层头记录…

优化问题的拉格朗日Lagrange对偶法原理

首先我们定义一般形式的求解x的优化问题&#xff1a; 表示优化的目标函数&#xff0c;上述为最小优化&#xff0c;实际上最大优化可以改写为的形式表示第i个不等式约束表示等式约束 1. Lagrange对偶问题 上述优化问题的拉格朗日Lagrange对偶法求解&#xff0c;是将上述带约束…

【Vue学习笔记6】好用的 Vueuse 工具包

1. 安装Vueuse VueUse 的官方&#xff08;https://vueuse.org/&#xff09;的介绍说这是一个 Composition API 的工具集合&#xff0c;适用于 Vue 2.x 或者 Vue 3.x&#xff0c;用起来和 React Hooks 还挺像的。 VueUse 插件的安装 npm install vueuse/core2. 实现全屏功能 …

【网络安全】记一次杀猪盘渗透实战

看起来非常假的网站&#xff0c;这个网站是没有 cdn 的用的是 thinkphpk 框架搭建的。 先打一波 poc 没有效果 访问一下后台直接在 url 后面加/admin。 一个开源的 cms 还没有验证码尝试用 burp 进行爆破&#xff0c;首先在火狐上设置代理 ip 为 127.0.0.1 代理端口为 8081。 B…

GPT详细安装教程-GPT软件国内也能使用

GPT (Generative Pre-trained Transformer) 是一种基于 Transformer 模型的自然语言处理模型&#xff0c;由 OpenAI 提出&#xff0c;可以应用于各种任务&#xff0c;如对话系统、文本生成、机器翻译等。GPT-3 是目前最大的语言模型之一&#xff0c;其预训练参数超过了 13 亿个…

ChatGPT终于被我问到胡说八道的程度了!

问&#xff1a;Python是强类型语言&#xff0c;还是弱类型语言 chatgpt&#xff1a;Python是强类型语言。Python很少会隐式地转换变量的类型&#xff0c;所以Python是强类型的语言 问&#xff1a;什么是强类型语言 chatgpt&#xff1a;强类型语言是指在编程语言中&#xff0…

Packet Tracer - 配置交换机端口安全

Packet Tracer - 配置交换机端口安全 地址分配表 设备 接口 IP 地址 子网掩码 S1 VLAN 1 10.10.10.2 255.255.255.0 PC1 NIC 10.10.10.10 255.255.255.0 PC2 NIC 10.10.10.11 255.255.255.0 非法笔记本电脑 NIC 10.10.10.12 255.255.255.0 目标 第 1 部…

MTK6765安卓智能模组5G核心板联发科MTK方案主板开发板

联发科MTK6765这是一款12纳米八核A53处理器&#xff0c;最高运行速度可达2.3GHz。它使用Android 9.0操作系统&#xff0c;配备2G16G内存&#xff0c;也支持其他选项1G/3G/4G8G/32G/64G。 此外&#xff0c;它支持全球主流频段&#xff0c;包括默认的国内频段以及2G GSM、2G/3G E…

学生台灯什么牌子好对眼睛好?专业护眼灯的学生台灯分享

据报告统计&#xff0c;2022年我国儿童青少年总体近视率为52.7%&#xff0c;其中6岁儿童为14.3%&#xff0c;小学生为35.6%&#xff0c;初中生为71.1%&#xff0c;高中生为80.5%&#xff0c;这些数据让人不寒而栗&#xff01; 专家表示&#xff0c;导致儿童青少年近视的因素&am…

离散数学下--- 代数系统

代数系统 定义&#xff1a; 代数系统是用代数运算构造数学模型的方法。 • 通过构造手段生成&#xff0c;所以也称代数结构 • 代数运算&#xff1a;在集合上建立满足一定规则的运算系统 &#xff08;一&#xff09;二元运算 二元运算的定义 二元运算需要满足的两个条件&a…

在Ubuntu18.04中安装uWebSockets库

目录 1.下载uWebSockets库2.下载uSockets3.安装openssl开发包4.编译首先说明这里使用的Ubuntu版本为18.04。 1.下载uWebSockets库 下载uWebSockets库有两种方式,一是终端,从Github中克隆uWebSockets库到Ubuntu本地文件夹,二是打开uWebSockets库下载链接自己下载到Windows,然…