Spring 框架介绍和使用

2023-05-16

微信公众号:运维开发故事,作者:老郑

历史的选择

Spring 作为一个基础的框架,是在 Java EE 开发历史中,是成千上万公司选择。单独使用 Spring 的非常少了,很多都是用 Spring-Boot/Spring-Cloud 来开发,但是 Spring 基础依然是我们使用的基石。我们将一起来聊一聊 Spring 的基本使用。首先我们一起来了解一下 Spring 框架整体架构图如下:图片

  1. 数据访问/集成,包括 JDBC 、ORM、OXM、JMS 和 Transaction 模块;

  2. WEB 模块,包括 WebSocket、Servlet、Web、Porlet 模块;

  3. 核心容器,包括 Bean 模块、Core 模块、Context 模块 和 SpEL 模块;

  4. 其他部分,包括:AOP、Test 等模块

Spring 同类框架

  • Micronaut

  • Quarkus

Spring 核心功能

核心功能:控制反转(IOC) 、AOP 非核心功能:事件驱动、国际化、资源管理,数据绑定、类型转换 、SpEL、单元测试等。

PS:核心功能,在本文会有使用实践。

Spring Bean 容器

控制反转(IOC)是 Spring 框架的核心功能之一,其本质的就是将用户创建 Bean 的过程赋予给 IOC 容器去完成,实现 Bean 创建权利的反转为容器来创建 Bean 和依赖 Bean 。

图片

image.png

Bean 创建

Spring 容器创建 Bean 只需要三个步骤:

  1. 定义 Bean

  2. 创建 Bean 容器/Bean 工厂

  3. 获取 Bean 对象

举一个例子:

public class TestMain {

    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);
        Student student = applicationContext.getBean(Student.class);
        student.study();
        student.sleep();
        student.study();
    }
}

@Configuration
@Import(Student.class)
class AppConfig {

}

@Component
class Student {

    private String name;

    private Integer source;

    public void study() {
        System.out.println("学习中...");
    }

    public void sleep() {
        System.out.println("休息中...");
    }
    // setter getter
}

运行上面的代码我们可以得到一下结果:

学习中...
休息中...
学习中...

上面的代码执行什么呢?其实我们可以将 ApplicationContext理解为 Spring 容器对象,然后我们在 AppConfig 配置类中去定义 Spring 容器去帮助我们加载那些 Bean ,最后我们通过 getBean 方法获取我们注册的 Bean 对象。如下图:图片在这个过程中使用到那些关键的接口/类呢?

  • BeanFactory� 是 Bean 的抽象工厂,也就是我们 ApplicationContext 的一个父接口。

  • BeanDefinition� 是 Bean 的定义信息, 比如 beanName, className, isAbstract� 等 Bean 定义信息。

注入依赖 (DI)

Spring IOC 容器主要是解决了 Bean 的创建和依赖管理的问题。我们常见的有两种依赖注入方式:

  1. 属性注入

  2. 构造方法注入

属性注入

通过成员属性的方式实现 Bean 的自动注入

@Component
class Student {
    @Autowired
    private Address address;
    // ...
}

@Component
class Address {
    // ...
}

  • 通过 @Component可以将 Student 、Address 类标记为一个 bean 对象

  • 通过 @Autowired可以将依赖 Bean 自动注入进来。

构造方法注入

通过构造方法实现 Bean 的自动注入

@Component
class Student {
    
 public Student(Address address) {
        this.address = address;
    }
}

@Component
class Address {
    // ...
}

Spring 的 IOC 解决了什么问题?

  1. 容器化,Spring包含并管理应用中对象的生命周期和配置(配置成单例还是原型,以及什么时候使用什么时候销毁)。

  2. 方便解耦,简化开发,Spring就是一个大工厂,可以将所有对象创建和依赖关系维护交给Spring管理,实现松耦合。符合高内聚低耦合的思想,这个特性也叫IOC(控制反转)。

  3. AOP编程的支持,Spring提供面向切面的编程,可以方便的实现对程序进行权限拦截、运行监控等功能,是通过动态代理和CGlib实现的,底层原理是反射。

  4. 声明式事务的支持,通过AOP来实现。不需通过编程的方式而进行管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明,便可将事务规则应用到业务逻辑中。

  5. 方便程序的测试,Spring对Junit4的支持,可以通过注解方便的测试Spring程序。

  6. 方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如Struts2、Hibernate、MyBatis等)。

  7. 异常处理,Spring提供方便的API把具体技术相关的异常转化为一致的unchecked异常(比如由JDBC、Hibernate或者JDO抛出的异常)。SpringMVC也有一个异常集中处理的思想,将异常抛给SpringMVC框架,由框架来处理异常。

  8. 降低JavaEE API的使用难度,Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

Spring AOP 面向切面

AOP(Aspect Oriented Programming)是面向切面的意思。

理解 AOP

Java 是一个面向对象(OOP)的编程语言,但是它有一个弊端就是需要为多个不具有继承关系的对象引入一个公共行为时,例如:日志记录、权限验证、事务管理、访问统计等公共行为,这样不便于维护,而且有大量重复代码,AOP 可以实现和 AOP 的互补。

举个例子: 我们有两个逻辑登录业务、订单业务,需要在他们调用前后进行:权限验证、日志记录等公共逻辑。

  1. 通过 OOP 的方式实现我们需要做一个逻辑模板:权限验证,具体逻辑(登录、订单),日志记录。

  2. 通过 AOP 的方式实现我们只需针对具体逻辑(登录、订单)前后做一个自定义切点,进行权限验证、日志记录。

如下图:图片经过 AOP 方式处理过后,我们可以减少公共对象的引用、通过非继承的方式来处理切入逻辑的拦截,实现公共逻辑和业务的逻辑的松耦合关系。

AOP 实现

Spring 通过代理的方式去实现 AOP,Java 代理的两种模式:静态代理、动态代理。

  • 静态代理:静态代理是指在程序运行前,可以理解为是 .java 文件编译后就存在代理类的字节码 .class 文件。

  • 动态代理:动态代理指在程序运行期间通过 JVM 反射等动态机制,在运行期生成代理对象确定代理逻辑。

Spring 的两种代理模式:

  • JDK 代理:核心类 JdkDynamicAopProxy。

  • GCLIB 代理:核心类 ObjenesisCglibAopProxy。

两种代理的选择:如果 Bean 实现了接口就采用 JDK 代理, 如果没有实现就采用 GCLIB 代理。

AOP 使用

假设已经有一个 UserService 类提供了登录业务,我们需要对该业务做一个【权限验证】、【日志记录】这两个公共逻辑,在不修改 UserService 类代码的前提下就可以通过 AOP 来解决。示例如下:

// 1. 测试类
public class AopTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(AopConfig.class);
        UserService userService = applicationContext.getBean(UserService.class);
        userService.login("admin", "123456");
    }
}

// 2. 配置类
@EnableAspectJAutoProxy
@Configuration
@Import({UserService.class, ValidateAspect.class})
class AopConfig {


}

// 业务类
@Component
class UserService {
    public String login(String username, String password) {
        System.out.println("username:" + username + ",password:" + password);
        return "ok";
    }
}

// Aspect
@Aspect
@Component
class ValidateAspect {

    @Pointcut("execution(public * io.zhengsh.simu.spring.UserService.*(..))")
    public void servicePoint() {
        // Do nothing
    }


    @Around("servicePoint()")
    public Object doAroundService(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("validate param invoke !!!");
        return joinPoint.proceed();
    }
}



maven 依赖

<!-- Spring核心依赖 -->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <!-- Spring beans包-->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <!-- Spring 容器包 -->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
  </dependency>

  <!-- aop -->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
  </dependency>

  <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.9.1</version>
  </dependency>

参考文档

  • Spring 官方文档

  • 骆驼整理说-Spring AOP

  • Java-为什么使用Spring框架

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring 框架介绍和使用 的相关文章

随机推荐

  • FTP上传中文设置

    package com wq test import java io File import java io FileInputStream import org apache commons net ftp FTPClient impor
  • FTP上传中文文件到中文路径

    package com wq test import java io File import java io FileInputStream import org apache commons net ftp FTPClient impor
  • leveldb之log文件

    leveldb之log文件 1 log文件在LevelDb中的主要作用是系统故障恢复时 xff0c 能够保证不会丢失数据 因为在将记录写入内存的Memtable之前 xff0c 会先写入Log文件 xff0c 这样即使系统发生故障 xff0
  • springboot @Slf4j 只显示Error 日志,不显示INFO日志 和DEBUG 日志

    问题 xff1a springboot 使用 64 Slf4j 注解的 log debug log info log error 只显示ERROR日志 xff0c 不显示DEBUG和INFO日志 原因 xff1a application p
  • 盘点 | 2023年最值得学的编程语言TOP 5,Python再度夺冠!

    前言 在技术的推动发展中 xff0c 编程语言的作用功不可 目前在技术领域约有600种语言 xff0c 人们对编程语言的认识和掌握情况每年都在变化 与此同时 xff0c 新兴的编程语言往往具有引人注目的元素和功能 2023年热门的编程语言有
  • python socke ftp功能实现 shell命令,上传,下载

    python socke ftp功能实现 shell命令 xff0c 上传 xff0c 下载 网上教程多 xff0c 但是都不全 xff0c 只有下载代码 本人练习 xff0c 附加了注释 xff0c 帮助新人练习 一定要吃透socket来
  • jumpserver 修改源码实现密钥+密码

    背景 云主机登录 密钥 43 密码 xff0c jumpserver登录只能配置自动登录 xff0c 或者手动登录不能满足 修改 如果设置密码为chongzhi 就必须重新录入密码 vi opt coco coco proxy py 39行
  • uml学习过程7-顺序图

    描述强调消息时间顺序的交互图 对象 对象生命周期 消息 对象创建与销毁 动态建模 xff1a 顺序图 圆柱 xff1a 调用类 不表达逻辑判断 xff1a 例如 密码错误 xff0c 非空判断 这些用于活动图表达
  • springmvc错误跳转页面

    在做一个项目的时候 xff0c 为了界面美观及用户体验 xff0c 我们往往会设计自己的错误跳转页面 xff0c 而不是直接展示给用户一堆错误码 xff0c 为此我们需要配置自己的错误跳转页面 1 项目结构 2 web xml lt DOC
  • 下载进度条

    span class token doctype span class token punctuation lt span span class token doctype tag DOCTYPE span span class token
  • 域名绑定到github主页

    最近在通过网上的教程搭建自己的github主页 xff0c 虽然现在也是半成品 xff0c 但是其中有一些步骤以及参考的连接还是值得分享一下的 首先在godaddy上购买的 com域名 xff0c 因为看见大家都说购买国内的域名需要备案之类
  • c++面试宝典

    目录 一 多线程 二 指针 三 字符串 四 面向对象 五 基本用法 六 c 43 43 11 七 算法 c 43 43 面试必考多线程 xff0c 内存 xff08 智能指针 xff09 xff0c 常见算法 xff0c 设计模式 一 多线
  • ssh远程执行命令的方法

    设置免密登录之后 xff0c 通常ssh remote ip command 就可以方便的执行远程命令 如果遇到包含单引号或者双引号的命令 xff0c 执行不成功 xff0c 如 xff1a awk F 39 39 39 print 1 3
  • [海外上架必备][Android]Google原生代码崩溃符号生成的问题

    默认情况下 xff0c 原生代码库已从应用的发布 build 中移除 此移除操作包括移除应用所使用的所有原生库中包含的符号表及调试信息 移除原生代码库会显著缩减大小 xff1b 但是 xff0c 由于缺少信息 xff08 例如类和函数名称
  • “应版权方要求,文件无法下载”的解决方案

    应版权方要求 xff0c 文件无法下载 的解决方案 参考文章 xff1a xff08 1 xff09 应版权方要求 xff0c 文件无法下载 的解决方案 xff08 2 xff09 https www cnblogs com easyide
  • 分布式系统核心—日志

    分布式系统的核心组件 日志 有时也叫write ahead logs commit logs 或者事物 logs 通常指在应用所有的修改之前先写入日志 xff0c 一般会将重放日志 撤销日志都写进去 NoSQL数据库 KV存储 Hadoop
  • ctags使用方法 ctags的使用方法

    用 ctags 看代码时 xff0c 检索函数及变量使用的文件是 tags 文件 有时我们会定制检索的文件范围 xff0c 这时候就可以通过 ctags 命令的一些参数来控制 tags 文件的内容 1 xff1a 递归检索当前目录以下所有默
  • AFNetworking 介绍和简单实用

    AFNetworking github AFNetworking AFNetworking 是一个网络请求封装框架 xff0c 使用简单 xff0c 功能强大 xff1b 在AFNetworking 3 x版本 通过封装NSURLSessi
  • Tomcat端口冲突的解决方法

    1 输入以下两条命令 span class ruby span class hljs number 1 span dos窗口中输入 xff1a netstat ano findstr span class hljs number 8080
  • Spring 框架介绍和使用

    微信公众号 xff1a 运维开发故事 xff0c 作者 xff1a 老郑 历史的选择 Spring 作为一个基础的框架 xff0c 是在 Java EE 开发历史中 xff0c 是成千上万公司选择 单独使用 Spring 的非常少了 xff