认识Spring(下)

作者:~小明学编程 

文章专栏:Spring框架

格言:热爱编程的,终将被编程所厚爱。
在这里插入图片描述

目录

Spring更加高效的读取和存储对象

存储bean对象

五大注解

关于五大类注解

对象的注入

属性注入

构造方法注入

Setter注入

三种注入方式的区别

@Resource 和 @Autowired 的区别

Bean的作用域和生命周期

Spring的执行流程

Bean的生命周期


Spring更加高效的读取和存储对象

存储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">
    <content:component-scan base-package="com.beans"></content:component-scan>
</beans>

首先是我们所依赖的资源,其中com.beans是我们所要扫描的类的包。

五大注解

  1. Controller 控制器
  2. Service 服务
  3. Repository 仓库
  4. Configuration 配置
  5. Component 组件

利用上面这五大注解都可以完成我们对象的注入。

@Service
public class UserService {
    public void sayHi() {
        System.out.println("hi Service");
    }
}
@Repository
public class UserRepository {
    public void sayHi() {
        System.out.println("Hi Res");
    }
}
@Controller
public class UserController {
    public void sayHi() {
        System.out.println("hello");
    }
}
@Configuration
public class UserConfig {
    public void sayHi() {
        System.out.println("Hi Con");
    }
}
@Component
public class UserComponent {
    public void sayHi() {
        System.out.println("Hi Com");
    }
}

获取:

    public static void main1(String[] args) {
        //1.获取上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserController userController = context.getBean("userController",UserController.class);
        userController.sayHi();
        UserService userService = context.getBean("userService",UserService.class);
        userService.sayHi();
        UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
        userRepository.sayHi();
        UserConfig userConfig = context.getBean("userConfig",UserConfig.class);
        userConfig.sayHi();
        UserComponent userComponent = context.getBean("userComponent",UserComponent.class);
        userComponent.sayHi();
    }

获取的时候我们需要注意这个beanname,这个beanname是根据如下的逻辑。

关于五大类注解

既然我们五种注解的随便一种都能完成我们的对象的注入,那么我们为什么还是需要五种注解呢

 因为我们一个软件是分为多个层面的,分为多层有助于我们的管理和控制。

Configuration 就是配置层:关于当前项目中的所有配置,都会写在这个文件夹里。
Controller 就是控制层:就是前端参数校验,主要就是校验前端数据的合理性和正确性。
Service 就是服务层,负责数据的组装和接口调用。更直白的说,服务器九四 “牵线搭桥” 让程序去调用对应的功能/接口/服务。
Repository 叫做仓库,但其实是 数据持久层,也叫做 Dao 层,就是对数据进行持久化操作(对数据库进行增删改查操作)。

我们使用不同的注解便于我们了解不同的代码的功能同时也方便我们对代码进行一个管理。

当然这五大类注解之间是有一定的关系的:

 可以看到我们的configuration注解是调用了我们的component注解的,其它几个注解的实现方法也是如此,可以说我们的component注解是我们其它四大注解的一个父类。

对象的注入

前面我们了解了怎么样将对象给存储起来,也就是使用五大注解可以高效方便的将我们的对象给放在spring中,但是当我们想要使用的时候有没有什么方式可以比较高效的来使用呢,下面就介绍三种方式来实现我们对象的一个注入。

属性注入

通过 @Autowired 注入:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void sayHi() {
        userService.sayHi();
    }
}

这里我们就通过关键字Autoeired的关键字来直接实现我们对象的一个注入,然在下面的方法之中我们就可以直接调用我们注入好的对象的方法了。

    public static void main(String[] args) {
        //1.获取上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = context.getBean(UserController.class);
        userController.sayHi();//hi Service
    }

构造方法注入

@Controller
public class UserController {
//    @Autowired
    private UserService userService;
    public UserController(UserService userService) {
        this.userService = userService;
    }
    public void sayHi() {
        userService.sayHi();
    }
}

这里我们可以直接通过构造方法的方式来进行对象的一个注入,但是值得我们注意的是,当我们的构造方法不止一个的时候就必须要使用Autowired关键字了,不然会报错。

@Controller
public class UserController {
//    @Autowired
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    public UserController(UserService userService,int num) {
        this.userService = userService;
    }
    public void sayHi() {
        userService.sayHi();
    }
}

Setter注入

@Controller
public class UserController {
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        userService.sayHi();
    }
}

同样我们也可以使用Setter这样一个方法来进行一个注入。

三种注入方式的区别

  1. 属性注入特点是写法简单,但是通用性不好,只能运行在 IoC 容器下,如果是 非 IoC 容器的话,就会出现问题。
  2. 构造方法注入,通用性更好。因为构造方法的优先级是最高的。确保使用注入对象之前,对象一定初始化过了。当构造方法注入参数太多时,就需要检查自己的代码是否符合单一设计原则的规范了。构造方法注入,也是 Spring 推荐的注入方法。
  3. Setter 注入是早期 Spring 版本推荐的写法,但是通用性没有构造方法注入通用,因为只有一个参数。

@Resource 和 @Autowired 的区别

相同点:都可以完成对象的注入。

不同点:

  • 出身不同,@Resource 来自于 JDK,@Autowired 是由 Spring 框架提供的。
  • @Autowired 支持属性注入,构造方法注入 和 Setter 注入,而 @Resource 不支持构造方法注入。
  • 支持的参数不同:@Resource 支持更多的参数设置,比如 name、type 设置。而 @Autowired 只支持 required 参数设置。

Bean的作用域和生命周期

在我们使用bean的时候其实默认是用的同一个bean也就是说如果我们对其中的bean进行一个更改的话,那么当我们再次去使用这个bean此时依然是更改之后的bean。

@Component
public class UserBean {

    @Bean(name = {"user","user1"})
//    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User user2() {
        User user = new User(15,"lisi");
        return user;
    }
    @Bean(name = {"user2"})
    public User user1() {
        User user = new User(12,"zhangsan");
        return user;
    }
}
@Component
public class BeanScope1 {
    @Autowired
    private User user2;

    public User getUser() {
        user2.setStr("aaa");
        return user2;
    }
}
@Component
public class BeanScope2 {
    @Autowired
    private User user2;//user2必须事被注入过的

    public User getUser() {
        return user2;
    }
}

这个时候我们注入了两次bean对象,此时查看输入的结果:

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanScope1 beanScope1 = context.getBean(BeanScope1.class);
        System.out.println(beanScope1.getUser());
        BeanScope2 beanScope2 = context.getBean(BeanScope2.class);
        System.out.println(beanScope2.getUser());


    }

 可以看到我们在对其进行更改之后,再次注入仍然是更改之后的User。

产生这样的原因是因为 Bean 在 Spring 中,默认情况下是单例状态,也就是所有人的使用都是同一个对像。这样可以很好的节约资源,避免资源的浪费。

Bean 的六种作用域
singleton:单例作用域(默认)在这种模式下的 Bean 在 IoC 容器里面,只存在一个实例。
prototype:原型作用域(多例模式)每次对作用域下的 Bean 请求,都会创建新的实例,然后再去获取 Bean。
request:请求作用域(Spring MVC)每次 Http 请求会创建新的 Bean 实例,类似于 prototype。
session:会话作用域(Spring MVC)在一个 http session 中,定义一个 Bean 实例。记录用户的登录信息。
application:全局作用域(Spring MVC)更多人使用的时候,就用 application。也是单例模式,应用在 Web 应用的上下文信息。
websocket:Http WebSocket 作用域(Spring WebSocket)在 WebSocket 会话中使用。
 

当我们想要改变其作用域的时候可以通过@Scope 的注解来进行改变

可以看到此时我们 所注入的对象就都是新的对象了。

设置作用域的时候,只需要通过 @Scope 注解就可以了

  1. 直接设置值:@Scope(“prototype”)
  2. 使用枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Spring的执行流程

1.我们首先是要启动我们的容器,去加载我们的配置文件。

也就是我们上面的这段代码。

2.接着就是根据我们的配置来完成我们的bean初始化。

 通过扫描包中的spring注解。

3.注册 Bean 对象到容器中,只有在包扫描的路径上的类,且使用 Spring 的注解才可以被注册到容器当中。

 4.装配 Bean 属性,也就是把 Bean 注册到其他类当中:

Bean的生命周期

Bean的生命周期就是Baen从诞生到销毁的一个过程 。

  1. 实例化 Bean(为 Bean 分配内存空间)
  2. 设置属性(Bean 注入和装配)
  3. Bean 初始化                                                                                                                         a)执行各种通知(各种Aware)如:BeanNameAware,BeanFactoryAware,ApplicationContextAware 的接口方法。
    b)执行 BeanPostProcessor 初始化前置方法。
    c)执行 @PostConstruct 初始化方法,依赖注入操作之后被执行。
    d)执行自己指定的 init-method 方法(如果有指定的话
    e)执行 BeanPostProcessor 初始化后置方法。
  4. 使用 Bean
  5. 销毁 Bean,通过方法来销毁容器:如 @PreDestroy、DisposableBean、destroy-method



其大概的流程图就是这样的。

<?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">
    <content:component-scan base-package="com.beans"></content:component-scan>
    <bean id="beanLife"
          class="com.beans.BeanLife" init-method="init"></bean>
</beans>
package com.beans;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86184
 * Date: 2023-03-06
 * Time: 22:07
 */
@Component
public class BeanLife implements BeanNameAware {
    @PostConstruct
    public void Post() {
        System.out.println("PostConstruct");
    }
    @PreDestroy
    public void Pre() {
        System.out.println("pre");
    }
    public void use() {
        System.out.println("use");
    }
    public void init() {
        System.out.println("init");
    }
    public void setBeanName(String s) {
        System.out.println("通知");
    }
}

 执行流程如上。

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

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

相关文章

IPV6 资料收集

IPV6与IPV4区别 1、地址长度的区别&#xff1a;IPv4协议具有32位&#xff08;4字节&#xff09;地址长度&#xff1b;IPv6协议具有128位&#xff08;16字节&#xff09;地址长度。 2、地址的表示方法区别&#xff1a;IPv4地址是以小数表示的二进制数。 IPv6地址是以十六进制表…

4.1 读写不同数据源的数据

4.1 读写不同数据源的数据4.1.1 读写数据库数据1、数据库数据获取2、数据库数据存储4.1.2 读写文本文件1、文本文件读取2、文本文件存储4.1.3 读写Excel文件1、Excel文件读取2、Excel文件存储完整代码4.1.1 读写数据库数据 1、数据库数据获取 pandas提供了读取与存储关系型数…

为什么说网络安全行业是 IT 行业最后的红利?

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护 2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来 3-5 年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏…

Android OKHttp源码解析

Https是Http协议加上下一层的SSL/TSL协议组成的&#xff0c;TSL是SSL的后继版本&#xff0c;差别很小&#xff0c;可以理解为一个东西。进行Https连接时&#xff0c;会先进行TSL的握手&#xff0c;完成证书认证操作&#xff0c;产生对称加密的公钥、加密套件等参数。之后就可以…

jenkins打包发布前端项目

1.配置前端nodejs打包环境 1.1安装nodejs插件 1.2配置jenkins nodejs环境 2.下载git插件(使用此插件配置通过gitlab标签拉取项目) 3.创建一个自由风格的发布项目 4.配置项目构建流程 4.1添加钉钉告警 4.2配置参数化构建 4.3配置源码管理为git拉取项目 4.4配置构建环境 4.5配置…

Graphic Game(思维 + 模拟删点)

C-Graphic Game_2022年江西省大学生程序设计竞赛&#xff08;正式赛&#xff09; (nowcoder.com) Topic describes eightCirno被推荐了一个游戏&#xff0c;她决定今天和Daiyousei一起玩。最初&#xff0c;有一个具有2 n个顶点和m条边的图。在每一个转弯&#xff0c;Cirno和Da…

SpringBoot+Shiro框架整合实现前后端分离的权限管理基础Demo

记录一下使用SpringBoot集成Shiro框架实现前后端分离Web项目的过程&#xff0c;后端使用SpringBoot整合Shiro&#xff0c;前端使用vueelementUI&#xff0c;达到前后端使用token来进行交互的应用&#xff0c;这种方式通常叫做无状态&#xff0c;后端只需要使用Shiro框架根据前端…

【云原生进阶之容器】第五章容器运行时5.4--容器运行时之Firecracker

1 Firecracker诞生背景 近些年 AWS 非常推崇无服务器模式

用Cmake构建第一个C++项目

ps&#xff1a;由于工作需求&#xff0c;需要涉及到跨平台。 概念 Cmake是一个款平台的构建工具&#xff0c;可以自动生成各种不同平台和编译器的构建脚本&#xff0c;使得项目在不同平台和编译器下都能够正常构建和运行。 CMake有自己的一套语法&#xff0c;需要学习CMake的…

上海亚商投顾:两市成交创年内新高 人工智能再爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪三大指数今日高开高走&#xff0c;沪指震荡反弹逼近3300点&#xff0c;创业板指午后涨超1.7%&#xff0c;科创50指数…

springboot 配置文件、多环境配置、运行优先级

前言 提问&#xff1a;springboot项目&#xff0c;开发环境、测试环境和生产环境配置文件如何分开表示&#xff1f; 答&#xff1a;多profile文件方式 1、多环境配置&#xff08;profile&#xff09; 1.1、properties文件配置 application.properties&#xff1a;主配置文…

基于html+css的between布局

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

【算法系列之动态规划IV】完全背包

完全背包 解题思路 01背包的核心思路&#xff0c;为了保证每个物品仅被添加一次&#xff0c;01背包内嵌的循环是从大到小遍历。 for(int i 0; i < weight.size(); i) { // 遍历物品for(int j bagWeight; j > weight[i]; j--) { // 遍历背包容量dp[j] max(dp[j], dp…

【云原生】k8s集群命令行工具kubectl之应用部署命令详解

kubectl应用部署命令详解一、准备工作1.1、Replication Controller1.2、Deployment1.3、DaemonSet1.4、查看创建的svc和pod1.5、kubectl 命令自动补全设置二、应用部署命令2.1、diff2.2、apply2.3、replace2.4、rollout2.4.1、history2.4.2、pause2.4.3、resume2.4.4、restart2…

Java 常量池分析

Java常量池 常量池&#xff1a;存放所有常量 常量池是Class文件中内容最为丰富的区域。常量池对于Class文件中的字段和方法解析也有着至关重要的作用。 随着Java虚拟机的不断发展&#xff0c;常量池的内容也日渐丰富。可以说&#xff0c;常量池是整个Class文件的基石。 在版…

HMC717ALP3E-ASEMI代理ADI(亚德诺)车规级芯片HMC717ALP3E

编辑-Z HMC717ALP3E参数描述&#xff1a; 频率范围&#xff1a;4.8 - 6.0GHz 增益&#xff1a;12.5dB 噪声系数&#xff1a;1.3dB 输入回波损耗&#xff1a;8dB 输出回波损耗&#xff1a;13dB 1 dB压缩的输出功率&#xff08;P1dB&#xff09;&#xff1a;12dBm 饱和输…

2023首届大学生算法大赛 - 村庄

读题可以发现&#xff0c;如果两个村庄不能互相连通&#xff0c;那就算作一对 &#xff08;a<b&#xff09;。 显然是可以用floyd全局多源最短路来做的&#xff0c;如果不存在最短路&#xff0c;那么就是不能互通&#xff0c;但是这道题的数据范围N<10^5&#xff0c;跑f…

SpringCloud之Eureka原理分析与实战(注册与发现)

目录 1、从本质理解服务治理思想 2、为什么选择Spring Cloud服务治理组件 3、Spring Cloud Eureka服务发现 3.1 Eureka的优势 3.2 Eureka架构组成 3.3 搭建Eureka Server 实战 3.3.1 添加依赖 3.3.2 开启服务注册 3.3.3 添加YML配置 3.3.4 访问服务 3.4 搭建Eureka …

IT服务商服务运营方案--PIGOSS BSM +TOC 服务加工具的新型运维模式

该解决方案适用于各种数据中心端专业运维服务商&#xff0c;包括驻场服务商&#xff0c;MA服务商&#xff0c;ITO服务商&#xff0c;IDC服务商&#xff0c;云运维服务商等 PIGOSS 是专业服务商的共同选择 专业的服务团队离不开专业的技术平台和技术工具&#xff0c;PIGOSS TOC…

echarts柱状图

1、先展示效果图 2、直接上代码&#xff0c;copy代码进行调试便会懂&#xff08;导入echarts插件看之前的文章&#xff09; <template><div class"antigen-container"><div class"top-content"><span class"top-title"&g…
最新文章