前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场

Spring

原创
作者头像
用户11637817
发布于 2025-04-30 12:37:51
发布于 2025-04-30 12:37:51
20900
代码可运行
举报
运行总次数:0
代码可运行

一、Spring简介

1.spring是什么?

Spring 是一个开源的轻量级 Java 开发框架,旨在简化企业级应用开发。它通过控制反转(IoC)和面向切面编程(AOP)实现组件解耦和横切逻辑分离,提升系统的可维护性与扩展性。Spring 提供统一的事务管理、灵活的 Web 开发框架(Spring MVC),并支持与多种第三方技术集成。其生态系统包括 Spring Boot(快速构建应用)、Spring Cloud(微服务架构支持)等,已成为现代 Java 开发的核心技术之一

2.spring优势

  • 解耦性强:通过IoC容器实现依赖注入,降低模块之间耦合度,提升系统灵活性和可维护性。
  • 开发效率高:提供大量开箱即用的功能和自动配置(如Spring Boot),简化繁琐配置,加快开发进度。
  • 生态体系完善:涵盖了Web开发、数据访问、安全控制、微服务等各类场景,并且还支持快速构建复杂的应用系统。

3.spring的结构

Spring框架采用由内至外的同心圆分层架构:​​核心层​​由Spring Core(提供依赖注入与IoC容器)和Spring Context(管理Bean生命周期及上下文配置)构成;​​中间功能层​​向外扩展,包含Spring AOP(基于核心实现切面编程)、Spring JDBC(简化数据库操作抽象层)和Spring ORM(集成Hibernate等ORM框架);​​外层​​为Spring Web模块,支撑Web应用开发。如下图所示:

spring的结构图
spring的结构图

4.spring的核心概念

IoC(控制反转)是Spring框架的基础机制之一,他的核心思想是将对象的创建和依赖关系的管理从开发者手中剥离,转而交由Spring容器统一进行控制。只需通过XML配置、Java注解或Java配置类的方式声明组件及其依赖关系,Spring容器就会在运行时根据配置动态创建对象,并自动完成依赖注入。

AOP(面向切面编程)则聚焦于系统中横切关注点的解耦与复用。通过将日志记录、权限校验、事务管理等非功能性需求抽象为独立的切面,AOP能够在编译期、类加载期或运行期通过织入(Weaving)机制将这些逻辑动态注入到目标方法中。这种横向抽取的设计避免了业务代码的重复编写,提升了代码的可维护性。

IoC与AOP相辅相成:前者负责纵向的对象生命周期管理,后者则横向增强系统功能,二者共同构成了Spring框架高效、模块化的核心支撑体系。

5.spring IOC

关键字:IOC名词解释,作用是解耦,使用IOC容器管理项目组件之间的耦合关系。

IOC(Inversion of Control,中文释义:控制反转),是Spring框架的核心思想之一,主要用于解耦。IOC是指将创建对象的控制权转移给Spring框架进行管理,由Spring框架根据配置文件或注解等方式,创建bean对象并管理各个bean对象之间的依赖关系。使对象之间形成松耦合的关系,实现解耦。

6.ioc的好处

ioc的思想最核心的地方在于,资源不由使用资源者管理,而由不使用资源的第三方管理,这可以带来很多好处,比如在实际项目中一个 Service 类可能依赖了很多其他的类,假如我们需要实例化这个 Service,可能要每次都要搞清这个 Service 所有底层类的构造函数,这就变得复杂了。而如果使用 IoC 的话,只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。

7.ioc配置的方式

xml配置

顾名思义,就是将bean的信息配置.xml文件里,通过Spring加载文件来创建bean。这种方式出现很多早前的SSM项目中,将第三方类库或者一些配置工具类都以这种方式进行配置,主要原因是由于第三方类不支持Spring注解。

  • 优点: 可以使用于任何场景,结构清晰,通俗易懂
  • 缺点: 配置非常繁琐,不容易维护,枯燥无味,扩展性较差

举例:

代码语言:txt
AI代码解释
复制
<?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">
    <!-- services -->
    <bean id="userService" class="com.seven.springframework.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>
    <!-- more bean definitions for services go here -->
</beans>

java配置

将类的创建交给我们配置的JavcConfig类来完成,Spring只负责维护和管理,采用纯Java创建方式。其本质上就是把在XML上的配置声明转移到Java配置类中

  • 优点:适用于任何场景,配置方便,因为是纯Java代码,扩展性高,十分灵活
  • 缺点:由于是采用Java类的方式,声明不明显,如果大量配置,可读性比较差

举例:

代码语言:txt
AI代码解释
复制
@Configuration
public class BeansConfig {

    @Bean("userDao")
    public UserDaoImpl userDao() {
        return new UserDaoImpl();
    }

    @Bean("userService")
    public UserServiceImpl userService() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(userDao());
        return userService;
    }
}

注解配置

通过在类上加注解的方式,来声明一个类交给Spring管理,Spring会自动扫描带有@Component,@Controller,@Service,@Repository这四个注解的类,然后帮我们创建并管理,前提是需要先配置Spring的注解扫描器。

  • 优点:开发便捷,通俗易懂,方便维护。
  • 缺点:具有局限性,对于一些第三方资源,无法添加注解。只能采用XML或JavaConfig的方式配置

举例:

代码语言:txt
AI代码解释
复制
@Service
public class UserServiceImpl {

    @Autowired
    private UserDaoImpl userDao;

    public List<User> findUserList() {
        return userDao.findUserList();
    }

}

总结:

方式

适用场景

灵活性

可维护性

学习成本

XML配置

遗留系统/第三方库

★★★★☆

★★☆☆☆

★★☆☆☆

Java配置

复杂业务逻辑/条件化Bean

★★★★★

★★★★☆

★★★☆☆

注解配置

新项目/领域模型

★★★☆☆

★★★★☆

★★☆☆☆

8.AOP的设计原理和思想

术语解析:

  1. 连接点(Join Point):程序执行过程中的某个点,如方法调用或异常抛出。
  2. 切点(Pointcut):匹配连接点的表达式,指定在哪些连接点应用通知。
  3. 通知(Advice):在切点处要执行的代码,分为:
    1. 前置通知(Before):在方法执行前
    2. 后置通知(After):在方法执行后(无论成功还是异常)
    3. 返回通知(AfterReturning):在方法成功执行后
    4. 异常通知(AfterThrowing):在方法抛出异常后
    5. 环绕通知(Around):包围方法执行的前后
  4. 切面(Aspect):切点和通知的组合。
  5. 织入(Weaving):将切面应用到目标对象并创建新的代理对象的过程。

9.AOP的实现原理

简单理解:Spring会创建一个"代理"对象,这个代理对象包含原对象的所有功能,同时可以在方法调用前后添加额外的逻辑。

10. Spring AOP vs AspectJ

Spring AOP是AspectJ的简化版,两者有以下区别:

特性

Spring AOP

AspectJ

功能

基本的AOP功能

完整的AOP功能

织入时机

运行时

编译时、加载时

性能

相对较低

更高

学习曲线

较低

较高

使用场景

简单应用

复杂应用

在大多数应用场景中,Spring AOP所提供的功能已能充分满足业务需求,无需额外引入AspectJ框架。Spring AOP基于动态代理的实现方式在性能与复杂度之间取得了良好平衡,其轻量级特性更适合常规开发需求。

11.AOP的使用方式

定义切面类:

使用@Aspect注解标记一个类为切面类,示例代码如下:

代码语言:txt
AI代码解释
复制
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义一个切点,匹配 com.example.service 包下所有类的所有方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    // 可以定义更多的切点,例如匹配特定注解的方法
    @Pointcut("@annotation(com.example.annotation.Loggable)")
    public void loggableMethods() {}
}
定义前置通知

使用@Before注解标记一个方法为前置通知,在目标方法执行前执行,示例代码如下:

代码语言:txt
AI代码解释
复制
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切点...
    
    // 在 serviceMethods 切点处执行的前置通知
    @Before("serviceMethods()")
    public void logBeforeMethodExecution(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("Before executing method: " + className + "." + methodName);
    }

    // 在 loggableMethods 切点处执行的前置通知
    @Before("loggableMethods()")
    public void logBeforeLoggableMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("Before executing loggable method: " + className + "." + methodName);
    }
}
定义后置通知

使用@After注解标记一个方法为后置通知,在目标方法执行后执行,无论目标方法是否抛出异常,示例代码如下:

代码语言:txt
AI代码解释
复制
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切点...
    
    @Before("serviceMethods()")
    public void logBeforeMethodExecution(JoinPoint joinPoint) {
        // 前置通知逻辑...
    }

    @After("serviceMethods()")
    public void logAfterMethodExecution(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("After executing method: " + className + "." + methodName);
    }
}
定义返回通知

使用@AfterReturning注解标记一个方法为返回通知,在目标方法正常返回后执行,示例代码如下:

代码语言:txt
AI代码解释
复制
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切点...
    
    @Before("serviceMethods()")
    public void logBeforeMethodExecution(JoinPoint joinPoint) {
        // 前置通知逻辑...
    }

    @After("serviceMethods()")
    public void logAfterMethodExecution(JoinPoint joinPoint) {
        // 后置通知逻辑...
    }

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("Method " + className + "." + methodName + " returned with value: " + result);
    }
}
定义异常通知

使用@AfterThrowing注解标记一个方法为异常通知,在目标方法抛出异常后执行,示例代码如下:

代码语言:txt
AI代码解释
复制
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切点...
    
    @Before("serviceMethods()")
    public void logBeforeMethodExecution(JoinPoint joinPoint) {
        // 前置通知逻辑...
    }

    @After("serviceMethods()")
    public void logAfterMethodExecution(JoinPoint joinPoint) {
        // 后置通知逻辑...
    }

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        // 返回通知逻辑...
    }

    @AfterThrowing(pointcut = "serviceMethods()", throwing = "exception")
    public void logAfterThrowing(JoinPoint joinPoint, Exception exception) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("Method " + className + "." + methodName + " threw exception: " + exception.getMessage());
    }
}
定义环绕通知

使用 @Around 注解标记一个方法为环绕通知,环绕通知可以在目标方法执行前后都进行增强,并且可以控制目标方法的执行,示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切点...
    
    @Around("serviceMethods()")
    public Object logAroundMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        System.out.println("Before executing method: " + className + "." + methodName);

        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();

        System.out.println("After executing method: " + className + "." + methodName);
        System.out.println("Method execution time: " + (endTime - startTime) + " ms");

        return result;
    }
}

OP 注意事项

在使用 AOP 时,需要注意以下几点:

  • ​性能影响​​:AOP 会在目标方法执行前后添加额外的逻辑,可能会对性能产生一定的影响。因此,在生产环境中使用 AOP 时,需要谨慎评估性能开销。
  • ​切点表达式​​:切点表达式的编写需要准确无误,否则可能会导致切面不生效或对不需要的方法进行增强。可以通过在线工具或 IDE 插件来辅助编写和测试切点表达式。
  • ​循环依赖​​:在使用基于 XML 的方式配置 AOP 时,需要注意避免循环依赖问题。可以通过合理设计 Bean 的加载顺序或使用延迟加载来解决。
  • ​异常处理​​:在编写环绕通知时,需要正确处理异常,避免异常被吞没或导致事务回滚等意外情况。
  • ​兼容性​​:不同的 AOP 实现方式可能存在一些兼容性问题,特别是在与一些第三方库或框架集成时,需要进行充分的测试和验证。

总结

pring AOP通过@Aspect注解定义切面类,结合@Pointcut可灵活配置多种切点表达式(如包路径匹配或注解匹配),再通过@Before、@After、@AfterReturning、@AfterThrowing和@Around等通知注解实现不同增强逻辑。前置通知在目标方法执行前触发,后置通知无论是否异常都会执行,返回通知仅在正常返回时触发,异常通知捕获方法抛出的异常,环绕通知则能完全控制目标方法的执行流程并测量执行时间。但是使用时要注意能影响、切点表达式准确性、循环依赖风险、异常处理规范以及不同AOP实现方式的兼容性等问题。

二、spring的快速入门

1.创建一个spring项目

完成之后点击创建等待创建成功

创建完成后的项目结构如下

源代码写在src目录下

test目录主要是测试

插入取消访问 Maven 仓库査找 Spring 依赖:https://mvnrepository.com/

点击第一个

选择6.1.14后点击

选择Maven后将下面内容复制

复制后在pom.xml文件中粘贴

点击更新maven

在examp目录下创建java类

在创建的类中添加

选中前三个方法后点击鼠标右键生成

点击Getter 和 Setter

选中全部后点击确定

在main下创建一个目录

创建resources文件

在这个目录下创建spring配置文件

导入spring文件

代码语言:txt
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframeworkframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframeworkframework.org/schema/beans http://www.springframeworkframework.org/schema/beans/spring-beans.xsd">
</beans>

将User对象存储到Spring容器

调用实例打印user中的方法

成功打印出你好!spring

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Spring简介
    • 1.spring是什么?
    • 2.spring优势
    • 3.spring的结构
    • 4.spring的核心概念
    • 5.spring IOC
    • 6.ioc的好处
    • 7.ioc配置的方式
    • 8.AOP的设计原理和思想
    • 9.AOP的实现原理
      • 10. Spring AOP vs AspectJ
    • 11.AOP的使用方式
      • 定义前置通知
      • 定义后置通知
      • 定义返回通知
      • 定义异常通知
      • 定义环绕通知
  • 二、spring的快速入门
    • 1.创建一个spring项目
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档