初步认识spring,一问掌握spring应用知识文集。

在这里插入图片描述

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。
🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。
🎉欢迎 👍点赞✍评论⭐收藏

文章目录

  • 🏆 认识spring系列知识
    • 🔎一、认识spring系列(1)
      • 🍁 01. Spring 是什么?
      • 🍁 02. 使用 Spring 的好处?
      • 🍁 03. 什么是依赖,什么是依赖注入?
      • 🍁 04. Spring 如何实现 IOC 容器功能?
      • 🍁 05. 什么是 AOP(Aspect-oriented programming 面向切面编程)?
      • 🍁 06. Spring AOP 原理?
      • 🍁 07. AOP 核心概念?
      • 🍁 08. Spring 自动装配的优缺点?
      • 🍁 09. Spring 依赖检查机制?
      • 🍁 10. 实际开发过程中为什么拆分 Spring 配置文件?
      • 🍁 11. 采用何种策略拆分 Spring 配置文件?
      • 🍁 12. Spring 对持久层的支持?
      • 🍁 13. Spring 的事务机制?
      • 🍁 14. 什么是声明式事务?
      • 🍁 15. Spring 如何使用声明式事务管理 Hibernate 的事务?
      • 🍁 16. SpringMVC 工作机制?

🏆 认识spring系列知识

🔎一、认识spring系列(1)

🍁 01. Spring 是什么?

在这里插入图片描述

Spring 是一个开源的应用程序框架,它是为了简化 Java 应用程序的开发而设计的。Spring 提供了一种轻量级的、非侵入式的方式来组织和管理 Java 程序的组件,帮助开发者构建可扩展、模块化和高效的企业级应用程序。

Spring 的核心特点如下:

  1. 非侵入性:Spring 遵循"反转控制"(IoC)原则,通过依赖注入(DI)实现了控制反转。这意味着开发者不需要显式地创建和管理对象的依赖关系,而是通过配置(如 XML、注解或 Java Config)告诉 Spring 需要哪些对象以及它们之间的关系,Spring 会负责实例化和管理对象,并自动注入它们的依赖关系。

  2. 面向切面编程(AOP):Spring 提供了 AOP 支持,允许开发者通过声明方式来实现横切关注点(cross-cutting concerns)的模块化。通过 AOP,可以将与业务逻辑无关的功能(如事务管理、日志记录、安全性等)从核心业务逻辑中解耦,使得应用程序更加模块化、可维护和可扩展。

  3. 声明式事务管理:Spring 提供了对事务管理的支持,可以通过声明方式来管理事务,而无需编写繁琐的事务管理代码。开发者可以通过注解或 XML 配置来指定哪些方法需要具备事务性,并指定事务的传播行为、隔离级别和回滚规则等。

  4. 简化 JDBC 开发:Spring 提供了对 JDBC 的封装,简化了数据库操作的编码,开发者无需手动处理连接打开、关闭、异常处理和事务提交回滚等操作,可以更便捷地进行数据库操作。

  5. 集成其他框架:Spring 提供了与其他流行框架(如 Hibernate、MyBatis、Struts、Servlet、JMS 等)的集成支持,使得这些框架能够更好地配合使用,并通过 Spring 的特性提供更高级的功能。

总的来说,Spring 是一个功能强大且灵活的框架,通过轻量级的方式解决了企业级 Java 应用程序开发中的众多问题。它的核心原则是便于扩展、松耦合和可测试性,使得开发者可以更加专注于业务逻辑的实现,提高开发效率,并改善应用程序的可维护性和可测试性。

🍁 02. 使用 Spring 的好处?

在这里插入图片描述

使用 Spring 框架有许多好处,以下是一些主要的好处,并附有详细的示例说明:

  1. 简化开发:Spring 提供了依赖注入(DI)和控制反转(IoC)等特性,使得开发者可以更方便地管理组件之间的依赖关系,而不需要手动创建和管理对象的实例化过程。这简化了开发过程,减少了样板代码的编写。

    举例来说,在传统的开发方式中,需要手动创建对象,并显式地设置对象之间的依赖关系:

    UserService userService = new UserService();
    UserDao userDao = new UserDao();
    userService.setUserDao(userDao);
    

    而在使用 Spring 后,可以通过配置告诉 Spring 需要哪些对象以及它们之间的依赖关系,Spring 负责创建和管理对象,并自动注入它们的依赖关系:

    @Autowired
    private UserService userService;
    
  2. 提高可测试性:Spring 的 DI 特性使得代码更加松耦合,组件之间的依赖通过接口而不是具体的实现类来定义。这样,开发者可以更轻松地进行单元测试,通过传入不同的实现类来模拟不同的场景。

    举个例子,假设有一个 OrderService 类,它依赖于一个 OrderDao 接口来进行数据操作,我们可以使用 Spring 的 DI 来实现依赖注入,并在测试时提供一个模拟的 OrderDao 实现:

    public interface OrderDao {
        Order findById(long id);
    }
    
    public class OrderDaoImpl implements OrderDao {
        // 实现代码省略
    }
    
    public class OrderService {
        @Autowired
        private OrderDao orderDao;
        
        public Order getOrderById(long id) {
            return orderDao.findById(id);
        }
    }
    
    public class OrderDaoMock implements OrderDao {
        // 模拟实现代码省略
    }
    
    // 单元测试代码
    @Test
    public void testGetOrderById() {
        OrderService orderService = new OrderService();
        orderService.setOrderDao(new OrderDaoMock());
        
        Order order = orderService.getOrderById(123);
        
        // 断言和验证代码
    }
    

    在这个例子中,通过使用 Spring 的 DI,我们可以在测试时轻松地替换真实的 OrderDao 实现,并使用模拟的 OrderDaoMock 来检查 OrderService 的行为。

  3. 提供面向切面编程(AOP)支持:Spring 的 AOP 特性可以将与业务逻辑无关的代码(如事务管理、日志记录、性能监控等)从核心业务逻辑中分离出来,并将其模块化,提高代码的可维护性和可复用性。

    举个例子,假设我们需要在每次方法执行前后记录日志,并统计方法的执行时间,可以使用 Spring 的 AOP 功能来实现:

    public aspect LoggingAspect {
        private Logger logger = Logger.getLogger(LoggingAspect.class);
        
        pointcut methodExecution(): execution(* com.example.service.*.*(..));
    
        before(): methodExecution() {
            logger.info("Entering method: " + thisJoinPoint.getSignature().getName());
        }
    
        after(): methodExecution() {
            logger.info("Exiting method: " + thisJoinPoint.getSignature().getName());
        }
    
        after returning(Object result): methodExecution() {
            logger.info("Method returned: " + result);
        }
    
        after throwing(Throwable e): methodExecution() {
            logger.info("Exception thrown: " + e);
        }
    }
    

    在上面的代码中,我们定义了一个切面(aspect)类 LoggingAspect,使用 Spring 的 AOP 配置将它应用于所有 com.example.service 包下的方法。这样,在每次方法执行前后,都会记录相应的日志信息。

总的来说,Spring 框架的好处包括简化开发、提高可测试性、提供面向切面编程等。这些好处可以提高开发效率、代码可维护性和可扩展性,使

🍁 03. 什么是依赖,什么是依赖注入?

在这里插入图片描述
在软件开发中,依赖是指一个组件或对象需要依赖(使用或调用)另一个组件或对象来完成特定的功能或任务。依赖关系在代码中通常通过在一个类中引用另一个类的实例或通过调用另一个类的方法来表示。

依赖注入(Dependency Injection,简称 DI)是一种设计模式,旨在解耦组件之间的依赖关系,通过外部来管理和提供组件所需的依赖。相比于传统的创建和管理依赖关系的方式,依赖注入通过将依赖关系的创建和注入交给容器或框架来处理,从而简化了代码的编写和维护。

依赖注入的核心思想是,将一个组件所依赖的其他组件通过构造函数、属性注入或方法注入的方式来引入,而不是在组件内部创建或管理这些依赖。

下面以 Java 代码举例说明依赖注入的使用方法:

public class UserService {
    private UserDao userDao;

    // 构造函数注入
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    // 方法注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    // 使用依赖的方法
    public User getUserById(int id) {
        return userDao.getUserById(id);
    }
}

public interface UserDao {
    User getUserById(int id);
}

public class UserDaoImpl implements UserDao {
    // 实现代码省略
}

// 在代码的某处,通过依赖注入提供 UserService 所需的 UserDao 实例
UserDao userDao = new UserDaoImpl();
UserService userService = new UserService(userDao);

在上面的例子中,UserService 类依赖于UserDao 接口来获取用户信息。通过构造函数注入和方法注入的方式,将UserDao的实现类UserDaoImpl传入UserService,并在getUserById方法中使用注入的UserDao实例。

这种方式使得UserService类与UserDao的具体实现类解耦,提高了代码的灵活性和可测试性。在实际应用中,可以通过配置文件或依赖注入容器(如Spring)来自动管理依赖的创建和注入过程。

🍁 04. Spring 如何实现 IOC 容器功能?

在这里插入图片描述

Spring框架通过实现控制反转(Inversion of Control,简称 IoC)来实现IoC容器的功能。IoC是一种设计思想,它将程序的控制权由程序员转移到容器中,由容器来管理对象的创建、依赖注入和生命周期等。

Spring框架实现IoC容器功能的核心是Bean工厂(BeanFactory)和应用上下文(Application Context)。

  1. Bean工厂(BeanFactory):Bean工厂是Spring IoC容器的核心部分,负责创建和管理对象(Bean)。它通过读取配置文件或通过编码方式定义Bean的定义和配置信息,然后根据需求动态实例化和管理Bean对象。Bean工厂采用延迟加载方式创建Bean,只有在真正需要使用Bean时才进行实例化。

  2. 应用上下文(Application Context):应用上下文是Bean工厂的扩展,提供了更多的企业级功能和组件,如国际化、事件传播、资源加载、AOP等。它是Spring框架中最常用的IoC容器,它在获取Bean的同时会自动将依赖注入到Bean中,并负责管理Bean的生命周期。

Spring的IoC容器实现IoC的过程如下:

  1. 配置Bean:通过配置文件(如XML配置)或注解来定义Bean的定义和配置信息,包括依赖关系、属性值和生命周期等。

  2. 加载Bean配置:IoC容器解析配置文件,将配置信息加载到内存中,并创建相应的Bean定义信息。

  3. 实例化Bean:根据配置信息和依赖关系,IoC容器在需要的时候动态地创建Bean实例。

  4. 注入依赖:IoC容器自动将依赖的Bean注入到需要的Bean中,可以通过构造函数注入、属性注入或方法注入。

  5. 管理生命周期:IoC容器负责管理Bean的生命周期,包括初始化和销毁阶段。在Bean实例化后,可以执行一些初始化操作,如调用初始化方法、实现一些接口等。在容器关闭时,可以执行一些销毁操作,如释放资源、关闭数据库连接等。

通过IoC容器,Spring框架实现了组件之间的松耦合,提高了代码的灵活性、可测试性和可维护性。同时,也降低了对象的管理和维护成本。

🍁 05. 什么是 AOP(Aspect-oriented programming 面向切面编程)?

在这里插入图片描述

AOP(Aspect-oriented programming),中文翻译为“面向切面编程”,是一种编程思想或设计模式。它的核心思想是,将程序中的某个特定功能(比如事务、日志、安全等)独立出来,然后通过一种方式(称为“切面”)将其分离出来,从而使其不影响主要业务逻辑。

在传统的面向对象编程中,方法和类之间的关系是比较密切的,一个类会依赖于其他类的方法来实现自己的功能。这样的话就会导致两个问题,一个是代码耦合度高,一个是代码重复度高。当我们对一个方法增加某个通用功能的时候,就需要修改该方法的代码,这会导致代码的可维护性变差。而AOP通过将通用功能和主要业务逻辑分离,解决了这两个问题。

在Spring框架中,AOP可以通过AspectJ注解或XML配置来实现。在AOP中,将通用功能称为“切面”,将需要被增强的方法称为“连接点”。

常见的切面功能包括:

  1. 日志:记录方法的执行时间、请求参数、日志等。
  2. 安全:控制方法的访问权限,验证用户身份等。
  3. 事务:管理数据库事务,确保数据完整性和一致性。
  4. 前置、后置、异常、最终通知:在方法执行前、后、异常和返回结果后执行特定的代码。

AOP的实现原理主要是通过运行时代理机制来实现。Spring框架在运行时动态地把增强代码织入到连接点上,形成一个代理对象。而代理对象在执行方法的时候,会按照一定的顺序执行所有的增强代码和连接点上原有的代码。

下面是一个使用AspectJ注解实现AOP的例子,该例子使用AspectJ注解来实现计算方法执行时间的功能:

@Aspect
@Component
public class LogAspect {
    @Around("execution(* com.example.demo.service..*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();

        Object result = pjp.proceed();

        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;

        System.out.println(pjp.getSignature() + " executed in " + elapsedTime + " ms");

        return result;
    }
}

@Service
public class UserService {
    public void addUser(User user) {
        // 实现代码省略
    }
}

// 使用UserService的方法
userService.addUser(new User());

在上面的例子中,LogAspect是一个切面,它使用@Aspect注解标记,被Spring容器自动扫描并加载。在around方法中,使用@Around注解来标记需要织入的连接点(即目标方法),并在方法执行前、后记录时间。在使用UserService的方法中,Spring框架会自动将LogAspect织入到addUser方法中,来记录方法执行时间。

总之,AOP为我们提供了一种灵活并且可扩展的方式去实现一些通用的特殊功能,使得代码更加简洁、可维护和可扩展。

🍁 06. Spring AOP 原理?

在这里插入图片描述

Spring AOP 的核心原理是基于动态代理和反射机制来实现。

当一个 Spring 容器启动时,会把一个 AspectJ 切面(如下面的例子)转换为一个代理对象。 Spring 会拿到需要被代理的目标 Bean,然后根据 AspectJ 切面中对目标 Bean 方法的增强定义生成增强后代码,然后通过 JDK 动态代理(对实现接口的 Bean 进行代理)或者 CGLIB 代理(对没有实现接口的 Bean 进行代理)来返回代理对象。

@Aspect
public class LogAspect {
    @Around("execution(* com.example.demo.service..*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();

        Object result = pjp.proceed();

        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;

        System.out.println(pjp.getSignature() + " executed in " + elapsedTime + " ms");

        return result;
    }
}

在上面的例子中,@Aspect 注解表示这是一个切面类,其中 @Around 注解表示需要织入目标方法的通知类型为环绕通知。execution(* com.example.demo.service..*(..)) 表示需要增强的目标方法,使用 AspectJ 表达式语言进行匹配。

当执行目标方法时,Spring 会在代理对象中找到与目标方法匹配的增强方法,从而在目标方法执行前或后,或者在目标方法抛出异常时执行相应的增强代码。最终,代理对象会向调用者返回增强后的结果。

这就是 Spring AOP 的基本原理,通过动态代理和反射机制实现方法增强,实现了切面与主逻辑的解耦。同时,Spring AOP 支持基于注解和 XML 配置两种方式来声明切面和增强方法,极大地方便了开发人员的使用。

🍁 07. AOP 核心概念?

在这里插入图片描述

AOP(面向切面编程)的核心概念包括切面(Aspect)、连接点(Joinpoint)、切点(Pointcut)、通知(Advice)和织入(Weaving)等。

  1. 切面(Aspect):切面是一种将横切关注点(如日志、事务管理等)模块化的方法。它描述了一类横切关注点和需要在哪些连接点上应用这些关注点。切面的实现通常是一些类,其中包括了一些切入点和通知。在 Spring AOP 中,可以定义多个切面。

  2. 连接点(Joinpoint):连接点是一个应用程序中能够插入切面的一个点,这个点可以是方法的调用、对类成员的访问或者异常的处理等。Spring AOP 仅支持方法级别的连接点。

  3. 切点(Pointcut):切点定义了在哪些连接点上应用切面,它是连接点的集合。切点告诉框架哪些方法需要拦截,切点的定义通常是使用 AspectJ 切点表达式。例如,使用 @Pointcut 注解声明一个切点:

    @Pointcut("execution(* com.example.demo.service.*Service.*(..))")
    private void serviceMethods() {}
    

    上面的切点定义表示拦截 com.example.demo.service 包中所有 *Service 结尾的类的任意方法。

  4. 通知(Advice):通知是切面需要执行的具体操作,它定义了切面在连接点处执行的行为。在 Spring AOP 中,共定义了五种类型的通知:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。

  • 前置通知:在目标方法执行前调用通知方法。
  • 后置通知:在目标方法执行后调用通知方法。
  • 返回通知:在目标方法返回结果后调用通知方法。
  • 异常通知:在目标方法抛出异常后调用通知方法。
  • 环绕通知:包围目标方法,可以阻止目标方法的调用,或者在目标方法调用前后执行一些自定义逻辑。

上述五种通知都可以通过注解来声明,如下面的例子:

	// 前置通知
	@Before("execution(* com.example.demo.service..*(..))")
	public void beforeMethod(JoinPoint jp) {
	    // ...
	}
	
	// 后置通知
	@AfterReturning(pointcut = "execution(* com.example.demo.service..*(..))", returning = "result")
	public void afterReturning(JoinPoint jp, Object result) {
	    // ...
	}
	
	// 异常通知
	@AfterThrowing(pointcut = "execution(* com.example.demo.service..*(..))", throwing = "ex")
	public void afterThrowing(JoinPoint jp, Exception ex) {
	    // ...
	}
	
	// 环绕通知
	@Around("execution(* com.example.demo.service..*(..))")
	public Object aroundMethod(ProceedingJoinPoint jp) throws Throwable {
	    // ...
	}
  1. 织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。在 Spring AOP 中,织入可以实现通过代理来实现切面。Spring AOP 会在启动时扫描配置文件中的切点和增强器,当目标对象执行相关方法时,Spring AOP 会自动织入切面的增强。

织入可以分为三种类型:

  • 编译时织入(Compile-time weaving):切面在目标类编译时直接织入字节码中。这种织入方式需要特定的编译器支持,例如 AspectJ 编译器,它会将切面代码与目标代码合并,并生成被织入了切面逻辑的目标类。生成的字节码文件可以直接在应用程序中使用,而不需要额外的运行时操作。

  • 类加载时织入(Load-time weaving):切面在目标类加载时动态地织入。这种织入方式需要使用特定的类加载器,在目标类被加载的时候,通过字节码增强技术将切面逻辑织入到目标类中。相对于编译时织入,类加载时织入更加灵活,可以在不修改目标类源代码的情况下实现切面逻辑的织入。

  • 运行时织入(Runtime weaving):切面在运行时动态地织入。这是 Spring AOP 默认采用的方式。在运行时织入时,Spring AOP 使用代理对象包装目标对象,并在代理对象中织入切面逻辑。当目标对象的方法被调用时,代理对象会先执行切面逻辑,然后再调用目标方法。这种方式相对于编译时织入和类加载时织入更加灵活,因为它可以在应用程序运行时动态地添加、删除或修改切面的逻辑。

🍁 08. Spring 自动装配的优缺点?

Spring 的自动装配功能使开发人员能够自动将依赖注入到 Bean 中,而不需要显式地在配置文件中进行声明。这种自动装配的方式有以下优点和缺点:

优点:

  1. 减少了配置的工作量:自动装配可以减少编写显式配置的代码量,因为 Spring 可以自动解决大部分 bean 之间的依赖关系。这样一来,开发人员可以将更多的精力放在业务逻辑的实现上,而不需要过多关注 bean 之间的依赖关系。

  2. 提高了代码的可读性和可维护性:通过自动装配,可以更容易地理解 bean 之间的关系,使代码更加清晰、易于理解和维护。自动装配可以隐式地展示 bean 之间的依赖关系,而无需在配置文件中进行繁琐的显式声明。

  3. 提供了灵活的依赖注入策略:Spring 提供了多种自动装配的模式,如根据名称、类型或注解等方式进行匹配。这使得开发人员可以选择不同的依赖注入策略,根据实际需求进行灵活配置。

缺点:

  1. 隐式导致依赖关系不明显:自动装配可能导致依赖关系变得隐式,对于代码的理解和维护可能会有一定的困难。如果没有良好的文档或注释说明,很难直观地了解 bean 之间的关系。

  2. 可能引发冲突和不确定性:自动装配能够自动解决大部分的依赖关系,但在某些情况下可能会发生冲突或不确定性。例如,当存在多个符合自动装配条件的 bean 时,可能无法确定应该注入哪个 bean。

  3. 可能影响代码的可测性:由于自动装配依赖关系的逻辑通常隐藏在代码之外,可能会增加单元测试的复杂度。对于依赖注入的模拟和测试可能需要更多的工作和配置。

总的来说,自动装配是一种便捷而强大的特性,可以大大提高开发效率和代码的可读性。但在使用自动装配时,我们仍然需要慎重考虑和合理规划,以避免潜在的问题和不确定性。

🍁 09. Spring 依赖检查机制?

Spring 提供了依赖检查机制,用于确保在应用程序启动时能够正确地解析和注入所有必需的依赖关系。依赖检查可以通过以下两种方式进行:

  1. 基于注解的依赖检查:在 Spring 中,可以使用 @Autowired 注解来标记需要自动注入的依赖。当 Spring 容器初始化时,会自动解析并注入相应的依赖。如果存在无法解决的依赖关系(比如找不到匹配的 bean),Spring 将会抛出异常,指示依赖检查失败。

  2. XML 配置的依赖检查:在 XML 配置文件中,可以使用 <bean> 元素的 dependency-check 属性来指定依赖检查的级别。有以下几种选项:

    • none:不进行依赖检查,默认值。
    • simple:检查依赖的 bean 是否存在,但不检查依赖的 bean 的属性是否都已经注入。
    • objects:检查依赖的 bean 是否存在,并且检查依赖的 bean 的属性是否都已经注入。
    • all:检查依赖的 bean 是否存在、依赖的 bean 的属性是否都已经注入,并且检查依赖的 bean 是否自身具有正确的依赖关系。

无论是基于注解的依赖检查还是 XML 配置的依赖检查,一旦检查失败,Spring 就会抛出异常来表示依赖关系无法满足。通过依赖检查机制,开发人员可以在应用程序启动时及时发现问题,并及时修复,以确保依赖关系的正确性和可用性。

🍁 10. 实际开发过程中为什么拆分 Spring 配置文件?

在实际开发过程中,将 Spring 配置文件拆分成多个文件可以带来以下好处:

  1. 提高可读性和可维护性:拆分配置文件可以使每个文件的大小和复杂度更容易管理。通过将相关的配置内容分割到不同的文件中,可以更容易理解和维护特定功能或模块的配置。这样可以提高代码的可读性,并且在需要调整或更新配置时更加灵活。

  2. 便于团队协作:拆分配置文件可以方便团队协作开发。不同的开发人员可以同时编辑各自负责的配置文件,而无需频繁地合并代码。这样可以提高开发效率,并且便于跟踪和处理代码变更。

  3. 提高可扩展性:通过将配置文件拆分为不同的模块,可以更容易地扩展应用程序。当需要添加新的功能或模块时,只需修改相关的配置文件,而不需要改动复杂的单一配置文件。这种拆分可以使应用程序的扩展更加灵活和可维护。

  4. 优化加载性能:拆分配置文件可以在启动时只加载必要的配置,从而提高应用程序的启动性能。当应用程序规模变大时,单一的配置文件可能变得庞大,加载时间也会随之增加。通过将配置文件拆分为多个模块,可以按需加载,减少加载和解析的时间。

  5. 分离关注点:拆分配置文件可以将不同的关注点分离开来,使代码更加清晰和易于理解。不同的配置文件可以专注于特定的功能、依赖关系或配置细节,使得代码更具可读性和可维护性。

需要注意的是,在拆分配置文件时,需要合理规划和组织文件之间的依赖关系,以确保加载和解析的正确顺序。可以使用 Spring 提供的 <import> 元素来引入其他配置文件,建立起不同文件之间的依赖关系。

🍁 11. 采用何种策略拆分 Spring 配置文件?

在实际项目中,可以采用以下几种策略来拆分 Spring 配置文件。

  1. 基于业务功能:将配置文件按照不同的业务模块或业务功能进行分离,例如一个电商应用中,可以通过将商品、订单、库存等不同模块的配置文件分离开来,使得配置更加清晰、易于管理和维护。

  2. 基于环境:将配置文件按照不同的部署环境(如开发、测试、生产等)分离开来,在不同的环境针对不同的配置进行定制,这样可以简化应用程序在不同环境下的部署流程,提高了可维护性和可重用性。

  3. 基于技术层次:将配置文件根据不同的技术层次进行分离,如将数据源、MVC、AOP 等不同框架或技术分离成不同的配置文件,便于调试、维护和升级。

  4. 基于 Spring 模块:将 Spring 自身的配置文件按照模块进行分离,如将 Spring 核心、Spring AOP、Spring MVC 等不同模块的配置文件分离开来,以便更好地掌握 Spring 框架的使用和细节。

  5. 基于公共配置与个性化配置:将通用的配置文件与各自独立的个性化配置文件分离开来,如将数据库连接信息、线程池等通用配置放在一个配置文件,而将各模块独有配置分别放在各自的配置文件中,以方便维护和管理。

在实际开发过程中,选择何种策略需要根据实际情况和需求制定,进行灵活组合和调整。无论采用哪种策略,拆分出来的配置文件应该有良好的命名规范和注释说明,以便于其他开发人员理解和修改。

🍁 12. Spring 对持久层的支持?

Spring 提供了多种方式来支持持久层开发,以方便与数据库进行交互和数据持久化。以下是 Spring 对持久层的几种主要支持方式:

  1. JDBC:Spring 提供了对 JDBC 的封装和简化,使得使用 JDBC 进行数据库操作更加方便和高效。通过 Spring 的 JdbcTemplate 和 NamedParameterJdbcTemplate,可以简化 JDBC 的繁琐操作,进行数据的读取、更新、插入和删除等常见操作。

  2. ORM 框架集成:Spring 与多个主流的 ORM 框架(如Hibernate、MyBatis)进行了集成,使得开发者可以使用这些 ORM 框架来操作数据库,并享受 Spring 提供的事务管理、声明式事务等特性。通过使用 Spring 提供的事务管理特性,可以更方便地管理和控制事务的边界。

  3. JPA 集成:Spring 支持 Java Persistence API(JPA)规范,并提供了对 JPA 的集成支持。通过 Spring 的 JPA 支持,可以更方便地配置和管理 JPA 实体管理器、事务,以及使用 JPA 的各种功能进行对象和数据库的映射操作。

  4. NoSQL 数据库集成:除了关系型数据库,Spring 也支持 NoSQL 数据库的集成,如 MongoDB、Redis 等。Spring 提供了相应的模块和 API,使得开发者可以通过 Spring 进行与 NoSQL 数据库的交互和操作。

  5. 事务管理:Spring 提供了强大的声明式事务管理支持,可以将事务的管理从代码中解耦出来。通过配置事务管理器和声明式事务定义,可以在方法、类或者类的方法上使用注解来定义事务边界。

通过以上的持久层支持方式,Spring 提供了一种灵活和扩展的机制,使得开发者能够根据具体需求选择最合适的持久化技术,并通过 Spring 的统一接口和特性来简化数据库操作和事务管理的工作。

🍁 13. Spring 的事务机制?

在这里插入图片描述

Spring 的事务机制提供了一种简单且强大的方式来管理数据库事务。可以通过编程方式或者声明式方式来定义和管理事务。下面详细说明 Spring 的事务机制,并举例说明。

  1. 编程式事务管理:

    编程式事务管理是通过编写代码显式地管理事务。在代码中使用 TransactionTemplate 或者 PlatformTransactionManager 来启动和提交事务,手动处理事务的边界。例如:

    // 在代码中使用 TransactionTemplate 手动管理事务
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    public void performTransaction() {
        transactionTemplate.execute(status -> {
            try {
                // 执行数据库操作
                // ...
                return null; // 或者返回其他结果
            } catch (Exception ex) {
                status.setRollbackOnly(); // 如果发生异常,标记事务为回滚状态
                throw ex;
            }
        });
    }
    
  2. 声明式事务管理:

    声明式事务管理通过使用注解或 XML 配置来定义事务。开发者只需要在方法或类上添加注解或配置,而不需要编写大量的事务管理代码。Spring 使用 AOP 技术拦截方法调用,在事务的开始和结束时自动管理事务边界。例如:

    // 使用注解方式定义事务
    @Service
    public class UserService {
        @Autowired
        private UserRepository userRepository;
    
        @Transactional
        public User updateUser(User user) {
            // 执行数据库操作
            // ...
            return userRepository.save(user);
        }
    }
    
    <!-- 使用 XML 配置方式定义事务 -->
    <bean id="userService" class="com.example.UserService">
        <property name="userRepository" ref="userRepository" />
    </bean>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut expression="execution(* com.example.UserService.update*(..))" id="updateMethodPointcut" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="updateMethodPointcut" />
    </aop:config>
    

无论是编程式事务管理还是声明式事务管理,Spring 的事务机制提供以下特性:

  • 事务的传播行为:定义事务方法与当前事务的关系,例如 REQUIRED、REQUIRES_NEW 等。
  • 事务的隔离级别:定义事务之间的隔离级别,例如 READ_COMMITTED、SERIALIZABLE 等。
  • 事务的回滚规则:定义哪些异常触发事务回滚,例如指定 rollbackFor 属性。
  • 事务的超时设置:定义事务的超时时间,超过该时间将会回滚事务。
  • 事务的只读属性:定义事务是否只读,以优化并发性能。

通过 Spring 的事务机制,可以轻松地管理事务的边界,确保事务的一致性和完整性,同时简化了事务管理的复杂性。

🍁 14. 什么是声明式事务?

在这里插入图片描述
声明式事务是一种通过注解或 XML 配置的方式来定义事务的管理方式,而不需要在代码中显式地编写事务管理代码。开发者只需通过简单的配置,就可以实现自动化的事务管理,提高开发效率和代码的可读性。

在声明式事务中,开发者只需在需要事务支持的方法或类上添加相应的注解或配置,在方法执行前后,Spring 将自动拦截方法调用,并在事务的开始和结束时处理事务的提交和回滚。这样可以将事务管理从业务代码中分离出来,使代码更加集中于业务逻辑本身。

下面是几个声明式事务的示例:

  1. 使用注解方式定义事务:

    @Service
    public class UserService {
        @Autowired
        private UserRepository userRepository;
    
        @Transactional
        public void updateUser(User user) {
            // 执行数据库操作
            // ...
            userRepository.save(user);
        }
    }
    

    在上述示例中,通过在 updateUser 方法上添加 @Transactional 注解,声明该方法需要进行事务管理。当调用该方法时,Spring 将会自动管理该方法的事务边界。

  2. 使用 XML 配置方式定义事务:

    <bean id="userService" class="com.example.UserService">
        <property name="userRepository" ref="userRepository" />
    </bean>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut expression="execution(* com.example.UserService.update*(..))" id="updateMethodPointcut" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="updateMethodPointcut" />
    </aop:config>
    

    在上述示例中,通过 XML 配置将 userService 对象定义为一个事务代理对象,并指定了事务管理器 transactionManager。通过 <tx:advice><aop:advisor> 的配置,指定了哪些方法需要加入事务管理。

通过声明式事务,可以更加方便地管理事务的边界,不再需要手动编写事务的启动、提交和回滚代码。同时,声明式事务的配置方式也使得事务管理的逻辑与业务逻辑更好地隔离,提供了更好的代码可读性和可维护性。

🍁 15. Spring 如何使用声明式事务管理 Hibernate 的事务?

在 Spring 中,可以使用声明式事务管理来管理 Hibernate 的事务。下面是使用声明式事务管理 Hibernate 的步骤:

  1. 配置数据库连接和 Hibernate SessionFactory。可以使用 Spring 的配置文件(XML 配置)或者注解方式进行配置。

  2. 在 Spring 配置文件中配置事务管理器(TransactionManager)以及启用声明式事务管理。

    <!-- 配置数据源、Hibernate SessionFactory等 -->
    
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    

    上述示例中,使用了 HibernateTransactionManager 作为事务管理器,并将 sessionFactory 注入给它。然后通过 <tx:annotation-driven> 启用了基于注解的声明式事务管理。

  3. 在需要进行事务管理的方法上添加 @Transactional 注解。

    @Service
    public class UserService {
        @Autowired
        private UserDao userDao;
    
        @Transactional
        public void updateUser(User user) {
            // 执行业务逻辑
            userDao.update(user);
        }
    
        // 其他业务方法...
    }
    

    在上述示例中,使用了 @Transactional 注解来声明 updateUser 方法需要进行事务管理。当方法被调用时,Spring 将会自动开启事务、提交事务或回滚事务。如果方法抛出异常,事务将会被回滚。

通过上述步骤,就可以使用声明式事务管理来管理 Hibernate 的事务。Spring 将会在方法执行时自动开启事务、提交或回滚事务,无需手动编写事务管理的代码。这样可以简化代码,提高开发效率,并能够确保数据的一致性和完整性。

🍁 16. SpringMVC 工作机制?

在这里插入图片描述
Spring MVC 是一种基于 Java 的 Web 框架,它使用了前端控制器模式来处理 Web 请求并将其路由到相应的处理程序。下面是 Spring MVC 的工作机制:

  1. 客户端发起请求:当客户端(如浏览器)发送一个请求到服务器时,该请求会被发送到前端控制器。

  2. 前端控制器接收请求:前端控制器是 Spring MVC 的核心组件,它负责接收所有的请求,并将请求分发给合适的处理程序进行处理。在 Spring MVC 中,DispatcherServlet 是默认的前端控制器。

  3. 处理程序映射:前端控制器将请求的 URL 与配置中的处理程序进行映射。处理程序可以是一个 Controller 类的实例,它们负责处理请求并生成响应。

  4. 处理程序执行:一旦找到了匹配的处理程序,前端控制器将请求转发给该处理程序,处理程序执行相应的业务逻辑、访问数据库等。

  5. 视图解析:处理程序执行完成后,将会返回一个逻辑视图名。前端控制器将根据视图解析器的配置,将逻辑视图名映射为物理视图。视图解析器可以将逻辑视图映射为 JSP 页面、Thymeleaf 模板等。

  6. 渲染视图:一旦找到了匹配的物理视图,前端控制器将请求转发给该视图,视图负责生成最终的响应。视图可以是一个 JSP 页面,它将使用数据填充模板,并将结果发送回客户端。

  7. 响应返回给客户端:视图渲染完成后,前端控制器会将响应发送回客户端,并结束整个请求-响应周期。

以下是一个简单的示例来说明 Spring MVC 的工作过程:

  1. 客户端发送请求:客户端发送一个 GET 请求 http://example.com/products.

  2. DispatcherServlet 接收请求:DispatcherServlet 是前端控制器,它接收到请求 http://example.com/products

  3. 处理程序映射:DispatcherServlet 根据配置的处理程序映射找到匹配的处理程序 ProductController

  4. 处理程序执行:DispatcherServlet 将请求转发给 ProductControllerProductController 执行相应的业务逻辑,如从数据库获取产品列表。

  5. 逻辑视图名返回:ProductController 返回逻辑视图名 “products”。

  6. 视图解析:DispatcherServlet 根据视图解析器的配置,将逻辑视图名 “products” 映射为物理视图 “products.jsp”。

  7. 渲染视图:DispatcherServlet 将请求转发给 “products.jsp”,JSP 页面将使用数据填充模板,生成最终的 HTML。

  8. 响应返回给客户端:DispatcherServlet 将生成的 HTML 响应发送回客户端,请求-响应周期结束。

通过以上的步骤,Spring MVC 可以将请求与处理程序、视图解析器和视图进行映射,使得开发者可以更加方便地处理 Web 请求和生成响应。

在这里插入图片描述

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

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

相关文章

关于“Python”的核心知识点整理大全26

目录 10.3.9 决定报告哪些错误 10.4 存储数据 10.4.1 使用 json.dump()和 json.load() number_writer.py number_reader.py 10.4.2 保存和读取用户生成的数据 对于用户生成的数据&#xff0c;使用json保存它们大有裨益&#xff0c;因为如果不以某种方式进行存储&#xf…

opencv 入门二(播放视频)

环境配置如下&#xff1a; opencv 入门一&#xff08;显示一张图片&#xff09;-CSDN博客 用OpenCV播放视频就像显示图像一样简单。唯一不同的是&#xff0c;我们需要某种循环来读取视频序列中的每一帧。 源码如下&#xff1a; #include <iostream> #include <str…

主馆位置即将售罄“2024北京国际信息通信展会”众多知名企聚京城

2024北京国际信息通信展&#xff0c;将于2024年9月份在北京国家会议中心盛大召开。作为全球信息通信技术领域的重要盛会&#xff0c;此次展会将汇集业内顶尖企业&#xff0c;展示最新的技术成果和产品。 目前&#xff0c;主馆位置即将售罄&#xff0c;华为、浪潮、中国移动、通…

PIC单片机项目(5)——基于PIC16F877A的多功能防盗门

1.功能设计 本次设计的功能如下&#xff1a;如果红外对管检测到有人经过&#xff0c;LCD1602可以显示&#xff0c;我设计的是显示字符串“someone”。 如果有人强行破门&#xff0c;FSR402压力传感器会检测到压力过大&#xff0c;然后触发蜂鸣器报警&#xff0c;LCD1602也显示“…

EMC测试与整改实践?|深圳比创达电子

电磁兼容(EMC)测试和整改是当今社会对电磁兼容(EMC)意识日益深入的表现&#xff0c;EMC测试与整改随着社会对电磁环境要求的不断提高&#xff0c;越来越受到重视&#xff0c;下面就EMC测试与整改实践进行一下详细介绍。 一、什么是EMC测试&#xff1f; EMC测试是指在一定的电…

rabbitmq界面主要参数分析

本篇主要分析rabbitmq broker界面参数 rabbitmq界面主要参数分析 1、connections User Name: user - 连接所使用的用户名。 State: running - 连接当前的状态&#xff0c;这里表明连接是活动的。 SSL/TLS: ○ - 表示这个连接没有使用SSL/TLS加密。 内部或受信任的网络中可能…

C# pictureBox显示一张图片,我想先释放这个图片以免占用无法修改,(旋转)改完再显示这张图片

效果 public static bool RotateFlip(MyDel Log, string fileName){try{string tempPath Path.GetTempFileName();using (Bitmap bmp new Bitmap(fileName)){float resolution 600; //x,y必须为这个数 误差小于-1bmp.RotateFlip(RotateFlipType.Rotate90FlipNone);bmp.Save(…

SQL Server 查询处理过程

查询处理--由 SQL Server 中的关系引擎执行&#xff0c;它获取编写的 T-SQL 语句并将其转换为可以向存储引擎发出请求并检索所需结果的过程。 SQL Server 需要四个步骤来处理查询&#xff1a;分析、代化、优化和执行。 前三个步骤都由关系引擎执行&#xff1b;第三步输出的是…

前端开发新趋势:Web3、区块链和虚拟现实

目录 前言 Web3&#xff1a;下一代互联网 区块链技术 去中心化应用程序&#xff08;DApps&#xff09; 区块链&#xff1a;重塑数字世界 数字钱包 NFT&#xff08;非同质化代币&#xff09; 虚拟现实&#xff1a;沉浸式体验 WebVR和WebXR 三维图形 新挑战与机会 性…

众和策略:短线交易看什么?短线交易看什么指标?

短线交易看什么&#xff1f; 1、k线 当k线出现黄昏十字星、黑乌鸦、乌云盖顶等卖出形状图时&#xff0c;是一种卖出信号&#xff0c;当k线出现早晨十字星、红三兵、等买入形状图时&#xff0c;是一种买入信号。 2、均线 当均线出现死叉、空头摆放时是一种卖出信号&#xff…

中国邮政旋转图像证码识别方案

最近研究了一下中国邮政旋转验证码的识别&#xff0c;居然正确率高达99%。所以可以说基本上的完美解决了这个问题&#xff0c;可以实现自动化验证。最后也给大家准备了识别代码。 1、下载图片 这里的图片一定要下载足够多&#xff0c;品种足够丰富&#xff0c;数据量越大&…

Kafka 安装与部署

目录 Kafka 下载 &#xff08;1&#xff09;将 kafka_2.11-2.4.1.tgz 上传至 /opt/software/ &#xff08;2&#xff09;解压安装包至 /opt/module/ [huweihadoop101 ~]$ cd /opt/software/ [huweihadoop101 software]$ tar -zxvf kafka_2.11-2.4.1.tgz -C ../module/&#…

小型洗衣机哪个牌子好十大排名?口碑好的小型洗衣机分享

现在很多小伙伴每天的工作压力已经非常大了&#xff0c;每天下班就希望可以躺平&#xff0c;但我们的贴身衣物还要每天来手动清洗&#xff0c;这对于上班人来说是一件很痛苦的事情&#xff0c;而现在市面上的内衣洗衣机真的给我们提供太多帮助&#xff0c;今天咱们来聊聊内衣洗…

IDEA中自定义注解支持SEL代码提示, 自定义参数, 函数参数, 返回值

背景 首先 IDEA 默认是不支持 SpEL 的代码提示的 根据网上教程, 我们只能使用java-annotations库, 并添加Language("SpEL")注解 但这样仅仅是能够支持SpEL表达式, 并不支持自定义变量, 也不支持提示方法参数和返回值. 尤其是对写框架和第三方库的人来说, 特别不友…

鸿蒙原生应用/元服务开发-Stage模型能力接口(七)

ohos.app.ability.EnvironmentCallback (EnvironmentCallback)一、说明 EnvironmentCallback模块提供应用上下文ApplicationContext对系统环境变化监听回调的能力&#xff0c;包括onConfigurationUpdated方法。本模块首批接口从API version 9 开始支持。后续版本的新增接口&…

Oracle11g登录方法

刚部署完Oracle11g可以使用如下方法登录 方法1 sqlplus sys/oracle as sysdba; 用系统用户登录 create user xy identified by test123; 创建用户 grant connect, resource,dba to xy; 授予权限 之后退出执行sqlplus登录命令 使用创建的用户登录 方法2 sqlplus ---登录…

计算机网络(四)

九、网络安全 &#xff08;一&#xff09;什么是网络安全&#xff1f; A、网络安全状况 分布式反射攻击逐渐成为拒绝攻击的重要形式 涉及重要行业和政府部门的高危漏洞事件增多。 基础应用和通用软硬件漏洞风险凸显&#xff08;“心脏出血”&#xff0c;“破壳”等&#x…

基于springboot+mybatis +mysql+vue人力资源管理系统(含论文)

基于springbootmybatis mysqljsp图书管理系统 一、系统介绍二、功能展示1.系统功能结构图2.登录3.个人信息编辑4.修改密码5.首页图表展示6.菜单分配7.员工请假8考勤数据导入 四、获取源码 一、系统介绍 本系统主要分四个模块&#xff0c;分别是系统管理和权限管理、薪资管理、…

计算机与自动诊疗仓:技术医学的新篇章

计算机与自动诊疗仓&#xff1a;技术医学的新篇章 一、引言 在当今的数字化时代&#xff0c;计算机科学技术与医学的结合已经成为医疗领域创新的重要驱动力。其中&#xff0c;自动诊疗仓的发展更是引领了技术医学的新潮流&#xff0c;为医疗服务带来了革命性的变革。本文将详…

Python爬虫全解析

一.爬虫--requests 1.常见的爬虫 -通用爬虫: 抓取系统重要组成部分。抓取的是一整张页面数据。 -聚焦爬虫: 是建立在通用爬虫的基础之上。抓取的是页面中特定的局部内容。 -增量式爬虫: 检测网站中数据更新的情况。只会抓取网站中最新更新出来的数据。 2.requests模块 re…