Spring 框架介绍和使用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring 框架介绍和使用

本文主要是对 Spring 的一个基本使用,建议阅读时间 5min。

历史的选择

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

image.png

  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

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 对象。如下图:

image.png

在这个过程中使用到那些关键的接口/类呢?

  • 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 的方式实现我们只需针对具体逻辑(登录、订单)前后做一个自定义切点,进行权限验证、日志记录。

如下图:

image.png


经过 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框架
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
8天前
|
前端开发 Java 数据库连接
Spring框架初识
Spring 是一个分层的轻量级开源框架,核心功能包括控制反转(IOC)和面向切面编程(AOP)。主要模块有核心容器、Spring 上下文、AOP、DAO、ORM、Web 模块和 MVC 框架。它通过 IOC 将配置与代码分离,简化开发;AOP 提供了声明性事务管理等增强功能。
55 21
Spring框架初识
|
2月前
|
XML 安全 Java
|
3月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
173 5
|
3月前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
154 0
|
27天前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
120 29
|
15天前
|
XML Java 开发者
通过springboot框架创建对象(一)
在Spring Boot中,对象创建依赖于Spring框架的核心特性——控制反转(IoC)和依赖注入(DI)。IoC将对象的创建和管理交由Spring应用上下文负责,开发者只需定义依赖关系。DI通过构造函数、setter方法或字段注入实现依赖对象的传递。Spring Boot的自动配置机制基于类路径和配置文件,自动为应用程序配置Spring容器,简化开发过程。Bean的生命周期包括定义扫描、实例化、依赖注入、初始化和销毁回调,均由Spring容器管理。这些特性提高了开发效率并简化了代码维护。
|
4月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
87 0
|
1月前
|
开发框架 运维 监控
Spring Boot中的日志框架选择
在Spring Boot开发中,日志管理至关重要。常见的日志框架有Logback、Log4j2、Java Util Logging和Slf4j。选择合适的日志框架需考虑性能、灵活性、社区支持及集成配置。本文以Logback为例,演示了如何记录不同级别的日志消息,并强调合理配置日志框架对提升系统可靠性和开发效率的重要性。
|
2月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
3月前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
227 53