SSM框架知识总结

天空闲话  金牌会员 | 2025-2-21 01:22:33 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 865|帖子 865|积分 2595

1.Spring常用的设计模式


  • 单例模式

    • Spring 容器默认情况下,Bean 的作用域是单例的。这意味着在整个应用程序生命周期内,一个 Bean 只有一个实例。例如,对于数据库连接池这个 Bean,只必要一个实例来管理所有的数据库连接请求。单例模式减少了对象的创建和烧毁开销,节省了体系资源。
    • Spring 通过维护一个单例 Bean 的缓存来确保只有一个实例存在。当第一次请求某个单例 Bean 时,Spring 会创建它并将其存储在缓存中,后续的请求直接从缓存中获取这个 Bean,而不是再次创建。

  • 工厂模式

    • 简单工厂模式:Spring 的 BeanFactory 就是简单工厂模式的体现。它负责创建和管理 Bean 对象。就像一个工厂生产产物一样,BeanFactory 根据配置(如 XML 配置文件或 Java 配置类)创建 Bean 实例。例如,在基于 XML 配置的 Spring 应用中,BeanFactory 读取<bean>标签的配置信息,包括类名、属性等,然后利用反射机制创建对应的 Bean。

  • 代理模式

    • JDK 动态代理:Spring AOP(面向切面编程)在为接口类型的 Bean 创建代理时,常常利用 JDK 动态代理。当有切面逻辑(如事件管理、日志记载)必要应用到一个接口的实现类时,Spring 会在运行时动态天生一个代理类,这个代理类实现了目的接口。代理类拦截对目的接口方法的调用,在方法执行前后插入切面逻辑。例如,在事件管理中,代理类在目的方法执行前开启事件,方法执行成功后提交事件,出现非常时回滚事件。
    • CGLIB 代理:对于没有实现接口的类,Spring AOP 利用 CGLIB 代理。CGLIB 通过继承目的类天生一个子类作为代理。例如,当要对一个具体的类进行性能监控切面时,CGLIB 代理类会重写目的类的方法,在方法调用前跋文载时间,从而实现性能监控,而不必要修改目的类的代码。

  • 模板方法模式

    • Spring 的 JdbcTemplate 是模板方法模式的范例应用。它界说了操作数据库的根本模板,包括获取数据库连接、执行 SQL 语句、处理效果集、释放连接等步调。此中获取连接和释放连接等步调是固定的,而执行 SQL 语句和处理效果集这些步调可以由用户通过提供回调方法(如RowMapper接口的实现)来定制。例如,在执行查询操作时,用户可以通过RowMapper接口实现将查询效果映射为 Java 对象的逻辑,JdbcTemplate 则按照其内部界说的模板方法流程完成整个数据库操作。

2.@Autowired和@Resource之间的区别?


  • 泉源和所属框架

    • @Autowired:是 Spring 框架提供的注解。它是 Spring 依赖注入(Dependency Injection,DI)机制的紧张组成部分,用于自动装配 Bean。Spring 通过扫描类路径,根据类型(byType)自动匹配并注入对应的 Bean。
    • @Resource:是 Java EE(Java Platform, Enterprise Edition)规范中的注解,在 JSR - 250 中界说。它并不是 Spring 特有的,不外 Spring 也支持这个注解用于依赖注入。

  • 注入方式

    • @Autowired

      • 默认是按照类型(byType)进行注入。例如,如果有一个接口UserService,而且有两个实现类UserServiceImpl1UserServiceImpl2,当在一个必要注入UserService的类中利用@Autowired注解时,Spring 会根据类型寻找对应的 Bean。如果只有一个UserService类型的 Bean,那么就会成功注入;如果有多个,就必要通过其他方式(如@Qualifier注解)来指定具体注入哪一个。
      • 也可以结合@Qualifier注解来按照名称(byName)进行注入。例如,@Autowired @Qualifier("userServiceImpl1") private UserService userService;,这里就是明白指定要注入名称为userServiceImpl1的UserService类型的 Bean。

    • @Resource

      • 默认是按照名称(byName)进行注入。它会先在容器中查找名称与注解中指定的名称(可以通过name属性设置,如@Resource(name = "userServiceImpl1"))相同的 Bean 进行注入。如果没有指定名称,就会按照变量名作为 Bean 名称来查找。
      • 如果按照名称找不到匹配的 Bean,才会按照类型进行注入。这与@Autowired的默认行为正好相反。


3. Spring常用注解


  • @Component

    • 作用:这是一个通用的 Spring 注解,用于将一个类标记为 Spring 容器中的组件。当 Spring 扫描到带有 @Component 注解的类时,会将其作为一个 Bean 进行管理。
    • 示例:假设我们有一个简单的服务类UserService,在类界说上添加@Component注解后,Spring 就会自动把这个类纳入容器管理。



  • 利用场景:用于自界说的普通 Java 类,只要盼望被 Spring 容器管理,都可以利用这个注解。

  • @Service

    • 作用:@Service 是 @Component 的一个特化注解,主要用于标注业务逻辑层(Service 层)的类。它的功能和 @Component 根本相同,只是语义上更加明白,用于区分差别层次的组件。



  • 利用场景:在构建企业级应用的三层架构(Controller - Service - DAO)时,用于标记服务层的类,让开发人员可以大概更直观地明白代码结构。

  • @Repository

    • 作用:这是专门用于数据访问层(DAO 层)的注解,用于将数据访问类标记为 Spring 容器中的 Bean。它还具有将数据访问非常(如 SQLException)转换为 Spring 的DataAccessException的功能,使得数据访问层的非常处理更加统一和易于管理.



  • 利用场景:在和数据库交互的应用中,用于标记所有和数据访问相关的类,包括对各种数据库(如 MySQL、Oracle 等)的操作类。

  • @Controller

    • 作用:用于标记 Spring MVC 中的控制器类。它将一个类标识为处理 HTTP 请求的前端控制器,共同 Spring MVC 的其他注解(如 @RequestMapping 等)可以方便地处理各种请求路径和请求方法。



  • 利用场景:在构建 Web 应用时,用于标记所有接收和处理用户请求的类,这些类通常会调用 Service 层的方法来完成业务逻辑,并将效果返回给视图层。

  • @Autowired

    • 作用:用于自动注入 Bean。Spring 会根据类型自动寻找匹配的 Bean 并注入到对应的变量、方法参数大概构造函数参数中。



  • 利用场景:在必要在一个类中利用其他 Bean 时,避免手动获取和实例化,通过这个注解可以方便地完成依赖注入,提高代码的可维护性和可测试性。

  • @RequestMapping

    • 作用:用于在 Spring MVC 中映射 HTTP 请求路径和请求方法。它可以用在类级别和方法级别,类级别的注解用于界说一个基础路径,方法级别的注解用于具体界说每个方法对应的路径和方法组合。



  • 利用场景:在构建 Web 应用的控制器中,用于界说每个请求处理方法对应的 URL 路径和请求方式,是实现前后端交互的关键注解之一。

  • @Configuration

    • 作用:用于标记一个类为 Spring 的配置类。在这个类中,可以通过@Bean注解界说各种 Bean,替代传统的 XML 配置文件。



  • 利用场景:在基于 Java 配置的 Spring 项目中,用于集中界说和管理所有的 Bean,使得配置更加灵活和易于维护,尤其适用于大型项目和团队协作开发。

  • @Bean

    • 作用:在@Configuration类中利用,用于界说一个方法,该方法返回的对象将作为一个 Bean 被 Spring 容器管理。



  • 利用场景:用于在 Java 配置类中创建和配置各种对象,包括自界说对象、第三方库对象等,是构建 Spring 容器的紧张本领之一。
4.什么是Spring IOC ?



  • 深入明白控制反转(IOC)概念

    • 控制权的转移
      1. public class LoginController {
      2.     private UserService userService = new UserService();
      3.     private UserDao userDao = new UserDaoImpl();
      4.     public void login(String username, String password) {
      5.         // 调用userService和userDao的方法来处理登录逻辑
      6.     }
      7. }
      复制代码
       

      • 在传统的程序设计中,对象的控制权完全在开发者编写的代码手里。例如,在一个简单的 Java Web 应用程序中,如果要实现用户登录功能,开发者可能会在LoginController类中手动创建UserService和UserDao的实例来处理用户登录的业务逻辑。像如许:
      • 这种方式下,LoginController类不仅要负责自身的业务逻辑(处理用户登录请求),还要负责创建和管理它所依赖的对象(UserService和UserDao)。而在 Spring IOC 模式下,控制权被反转到了 Spring 容器。Spring 容器就像一个大管家,它负责创建UserService和UserDao这些对象,LoginController只必要从容器中获取已经创建好而且配置好依赖关系的对象就可以了。


  • 详细分析依赖注入(DI)

    • 构造函数注入的细节
      1. public class OrderService {
      2.     private OrderDao orderDao;
      3.     public OrderService(OrderDao orderDao) {
      4.         this.orderDao = orderDao;
      5.     }
      6.     // 其他业务方法
      7. }
      复制代码



  • 参数匹配:当利用构造函数注入时,Spring 容器会根据构造函数的参数类型来匹配要注入的对象。例如,有一个OrderService类,它的构造函数接受一个OrderDao类型的参数:
  • 假设在 Spring 配置中有一个OrderDao的bean界说,容器在创建OrderService的实例时,会查找类型为OrderDao的bean,并将其作为参数传递给OrderService的构造函数。如果有多个OrderDao的实现类,还可以通过在配置中指定bean的名称大概利用@Qualifier注解等来精确匹配要注入的对象。
  • 对象的完备性包管:构造函数注入的一个优点是可以包管注入的对象在OrderService实例化时就已经准备好。如许可以确保OrderService对象从创建的那一刻起就处于一个完备的状态,不会出现由于某些依赖对象没有注入而导致的NullPointerException等问题。


  • Setter 方法注入的更多细节

    • 灵活性:Setter 方法注入提供了一种更加灵活的方式来注入依赖。例如,ProductService类有一个setProductDao的 Setter 方法:
    1. public class ProductService {
    2.     private ProductDao productDao;
    3.     public void setProductDao(ProductDao productDao) {
    4.         this.productDao = productDao;
    5.     }
    6.     // 其他业务方法
    7. }
    复制代码
        

    • 在某些情况下,可能并不必要在ProductService对象创建时就注入ProductDao对象。比如,ProductService对象可能有一个初始化阶段,在这个阶段之后才必要ProductDao对象来执行一些数据查询操作。此时,Setter 方法注入就可以在必要的时候再注入ProductDao对象,而不是像构造函数注入那样必须在对象创建时就完成注入。
    • 循环依赖处理:Setter 方法注入在处理某些循环依赖的情况时可能会更加灵活。例如,A类依赖B类,B类又依赖A类。在这种情况下,利用 Setter 方法注入可能更轻易办理循环依赖问题,由于对象可以先被创建,然后再通过 Setter 方法来办理相互之间的依赖关系,固然,Spring 在处理循环依赖时还有一些复杂的机制和限定。

5.什么是SpringAOP?


  • 概念界说

    • Spring AOP(Aspect - Oriented Programming,面向切面编程)是 Spring 框架提供的一种编程范式,用于在不修改原有业务逻辑代码的基础上,实现横切关注点(Cross - Cutting Concerns)的功能。横切关注点是指那些会分散在多个业务模块中的功能,如日志记载、事件管理、安全验证等。
    • 例如,在一个包含多个业务方法的体系中,可能每个业务方法都必要记载日志来跟踪其执行情况。如果不利用 AOP,就必要在每个业务方法中添加日志记载的代码,如许会导致代码冗余且难以维护。而 Spring AOP 允许将日志记载这个横切关注点从业务方法中分离出来,集中进行管理。

  • AOP 中的根本概念

    • 切面(Aspect):切面是一个包含了横切关注点相关逻辑的模块。它是 AOP 中的核心概念,将横切逻辑(如日志记载逻辑)封装在一个独立的单元中。切面由切点和通知组成。
    • 切点(Pointcut):切点用于界说在哪些连接点(Join Point)上应用切面的通知。连接点是程序执行过程中的某个特定位置,如方法调用、方法执行、非常抛出等。切点可以利用表达式来精确地指定在哪些类的哪些方法上应用切面。例如,可以界说一个切点,使其应用于某个包下所有以 “save” 定名的方法。
    • 通知(Advice):通知是切面中界说的在切点所匹配的连接点上执行的具体动作。Spring AOP 中有五种通知类型:

      • 前置通知(Before Advice):在目的方法执行之前执行的通知。例如,在业务方法执行前记载开始时间用于性能分析。
      • 后置通知(After Advice):在目的方法执行之后执行的通知。它不管目的方法是否抛出非常都会执行。比如,在业务方法执行后关闭数据库连接。
      • 返回通知(After - Returning Advice):在目的方法正常返回效果后执行的通知。可以用于对返回效果进行处理,如对返回的数据进行加密。
      • 非常通知(After - Throwing Advice):在目的方法抛出非常时执行的通知。用于处理非常情况,如记载非常信息到日志文件。
      • 围绕通知(Around Advice):围绕通知可以在目的方法执行前后都进行操作,它就像一个拦截器一样,可以控制目的方法是否执行、何时执行以及如何执行。例如,可以在围绕通知中实现缓存机制,先检查缓存中是否有目的方法的效果,如果有则直接返回,否则执行目的方法并将效果存入缓存。


  • 工作原理

    • Spring AOP 是基于代理(Proxy)模式实现的。当一个目的对象(被代理的对象,如业务服务类)被配置为必要应用 AOP 时,Spring 会为其创建一个代理对象。这个代理对象会拦截对目的对象的方法调用。
    • 以 JDK 动态代理为例(当目的对象实现了接口时利用),代理对象和目的对象实现相同的接口。当客户端调用目的对象的接口方法时,实际上调用的是代理对象的方法。代理对象会根据切点的界说,判断是否必要执行切面的通知。如果必要,就会按照通知的类型(前置、后置等)在合适的机遇执行通知中的逻辑,然后再调用目的对象的真实方法。
    • 例如,有一个UserService接口和它的实现类UserServiceImpl,而且配置了一个切面来记载UserService方法的执行日志。当客户端调用UserService接口的saveUser方法时,实际上调用的是 Spring 为UserServiceImpl创建的代理对象的saveUser方法。代理对象起首会检查日志记载这个切面的切点是否匹配saveUser方法,如果匹配,就会执行前置通知(记载方法开始执行的日志),然后调用UserServiceImpl的真实saveUser方法,末了执行后置通知(记载方法执行竣事的日志)。
    • 应用场景

      • 日志记载:如前面所述,AOP 可以方便地在多个业务方法中统一添加日志记载功能。可以记载方法的执行时间、参数、返回效果等信息,便于体系的监控和调试。
      • 事件管理:在企业级应用中,事件管理是非常紧张的。AOP 可以用于在多个业务方法周围添加事件控制逻辑。例如,对于数据库操作方法,在方法执行前开启事件,在方法正常执行完成后提交事件,在方法抛出非常时回滚事件。
      • 安全验证:可以在必要进行安全验证的方法调用前添加验证逻辑。例如,验证用户是否具有访问某个资源的权限。如果没有权限,就抛出非常大概返回错误信息,而不必要在每个业务方法中都编写安全验证的代码。


 6.Spring的循环依赖问题(重点)


  • 循环依赖的概念

    • 循环依赖是指在 Spring 容器中,两个或多个 Bean 之间存在相互依赖的关系。例如,有 Bean A 和 Bean B,Bean A 依赖于 Bean B,同时 Bean B 又依赖于 Bean A。这种相互依赖的情况可能会导致在对象创建和初始化过程中出现问题。
    • 从代码角度看,假设存在两个类ClassA和ClassB,在 Spring 配置中界说为两个 Bean。ClassA中有一个属性是ClassB类型,ClassB中也有一个属性是ClassA类型,像如许:
    1. public class ClassA {
    2.     private ClassB classB;
    3.     // 构造函数或Setter方法注入ClassB
    4. }
    5. public class ClassB {
    6.     private ClassA classA;
    7.     // 构造函数或Setter方法注入ClassA
    8. }
    复制代码

  • 循环依赖产生的问题及缘故原由

    • 对象创建的死循环:在没有适当处理机制的情况下,当 Spring 容器试图创建ClassA的 Bean 时,它发现ClassA依赖于ClassB,所以它会去创建ClassB。但在创建ClassB的过程中,又发现ClassB依赖于ClassA,于是又回头去创建ClassA,如许就陷入了一个无限循环的创建过程,导致程序无法正常运行。
    • 未初始化的对象引用:纵然通过某种方式避免了死循环,还可能出现另一个问题。例如,如果采取构造函数注入,当ClassA在构造函数中等待ClassB的完全初始化实例,而ClassB又在其构造函数中等待ClassA的完全初始化实例,如许两个对象都无法完成初始化,最终得到的是两个未完全初始化的对象引用,这可能会导致后续利用这些对象时出现NullPointerException或其他错误。

  • Spring 办理循环依赖的方式

    • 三级缓存机制(针对单例 Bean)

      • Spring 利用了三级缓存来办理单例 Bean 的循环依赖问题。这三级缓存分别是:

        • singletonObjects:这是一级缓存,用于存放完全初始化好的单例 Bean。一旦一个 Bean 完成了创建、属性注入和初始化等所有步调,就会被放入这个缓存中。
        • earlySingletonObjects:这是二级缓存,用于存放提前袒露的单例 Bean(还没有完成所有初始化步调)。当一个 Bean 在创建过程中发现存在循环依赖,而且必要将本身提前袒露出来以办理依赖问题时,就会先将本身放入这个缓存。
        • singletonFactories:这是三级缓存,存放的是创建单例 Bean 的工厂对象。这个工厂对象可以用于创建 Bean,同时也可以用于在循环依赖情况下获取提前袒露的 Bean。

      • 当 Spring 容器创建一个单例 Bean 时,起首会实验从singletonObjects缓存中获取,如果没有找到,就会创建这个 Bean。在创建过程中,如果发现存在循环依赖,就会将这个 Bean 提前袒露(放入earlySingletonObjects或通过singletonFactories来提供),使得其他依赖它的 Bean 可以获取到这个未完全初始化的 Bean,从而避免死循环。

      • 例如,假设创建ClassA,发现依赖ClassB,在创建ClassB时又发现依赖ClassA。此时,ClassA还没有完玉成部初始化,但可以通过三级缓存机制提前袒露本身。ClassB就可以获取到这个提前袒露的ClassA,完成本身的创建,然后ClassA再获取已经创建好的ClassB,完成本身的剩余初始化步调,末了将完全初始化好的ClassA放入singletonObjects缓存。


    • 构造函数注入的限定:Spring 在处理循环依赖时,对于构造函数注入有肯定的限定。由于构造函数注入要求在对象创建时就注入所有依赖,所以如果存在循环依赖且都是通过构造函数注入的情况,Spring 无法办理,会抛出BeanCurrentlyInCreationException非常。这是由于在构造函数注入的场景下,很难像 Setter 方法注入那样先创建一个未完全初始化的对象并袒露出来办理循环依赖。
    • Setter 方法注入的上风:Setter 方法注入在处理循环依赖时相对更灵活。在这种情况下,Spring 可以先创建对象,将其放入缓存(通过三级缓存机制),然后再通过 Setter 方法注入依赖。例如,ClassA和ClassB通过 Setter 方法注入相互依赖,Spring 可以先创建ClassA,将其放入缓存,然后在创建ClassB时,从缓存中获取ClassA,注入到ClassB中,反之亦然。

7.Bean的生命周期(重点)

在 Spring 框架中,Bean 的生命周期是指从 Bean 的创建、初始化到烧毁的整个过程。以下是 Bean 生命周期的详细过程:

  • 实例化
    Spring 容器根据配置信息,如 XML 配置文件或注解,利用反射机制创建 Bean 的实例。例如,当配置了一个@Component注解的类时,Spring 会在启动时扫描并实例化该类。
  • 属性赋值
    在 Bean 实例化后,Spring 会按照配置为 Bean 的属性进行赋值。可以通过 XML 中的<property>标签或@Autowired、@Value等注解来指定属性的值或依赖关系。
  • 初始化前
    在 Bean 的属性赋值完成后,会执行BeanPostProcessor的postProcessBeforeInitialization方法。这个阶段可以对 Bean 进行一些前置处理,例如修改 Bean 的属性值等。
  • 初始化
    Spring 会检查 Bean 是否实现了InitializingBean接口,如果实现了,则调用其afterPropertiesSet方法。别的,还可以通过在 Bean 类的方法上添加@PostConstruct注解来指定初始化方法,该方法也会在这个阶段被调用。初始化方法通常用于执行一些必要在 Bean 创建完成后立刻进行的操作,如资源的初始化、数据的加载等。
  • 初始化后
    执行BeanPostProcessor的postProcessAfterInitialization方法。这个阶段可以对 Bean 进行后置处理,例如为 Bean 天生代理对象等。
  • 利用
    Bean 初始化完成后,就可以在应用中被其他组件利用了。此时,Bean 已经处于可用状态,可以提供相应的服务和功能。
  • 烧毁前
    当 Spring 容器关闭时,会先执行DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法,允许在 Bean 烧毁前进行一些自界说的处理。
  • 烧毁
    Spring 会检查 Bean 是否实现了DisposableBean接口,如果实现了,则调用其destroy方法。别的,还可以通过在 Bean 类的方法上添加@PreDestroy注解来指定烧毁方法。烧毁方法通常用于释放 Bean 占用的资源,如关闭数据库连接、释放文件资源等。
  • 烧毁后
    Bean 烧毁完成后,它所占用的资源被释放,不再在 Spring 容器中管理,从内存中移除。
8.Mybatis的一级、二级缓存

MyBatis 提供了两级缓存机制:一级缓存和二级缓存,用于提升查询性能,减少数据库访问次数。
1. 一级缓存(Local Cache)



  • 作用范围:一级缓存是 SqlSession 级别的缓存,默认开启。
  • 生命周期:与 SqlSession 绑定,SqlSession 关闭或清空时,缓存失效。
  • 工作机制

    • 同一 SqlSession 中,相同查询语句和参数的效果会被缓存。
    • 执行更新操作(如 insert、update、delete)时,缓存会被清空,以包管数据一致性。

  • 特点

    • 自动启用,无需额外配置。
    • 仅对当前 SqlSession 有效,其他 SqlSession 无法共享。

2. 二级缓存(Global Cache)



  • 作用范围:二级缓存是 Mapper 级别的缓存,多个 SqlSession 共享。
  • 生命周期:与 Mapper 绑定,应用关闭或显式清空时,缓存失效。
  • 工作机制

    • 必要手动配置启用。
    • 多个 SqlSession 可以共享缓存数据。
    • 执行更新操作时,缓存会被清空。



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表