SSM框架

SSM框架

SSM框架是指Spring + SpringMVC + MyBatis框架组合。它是一种基于Java编程语言的Web开发框架。Spring是一个开源的JavaEE框架,提供了一个容器和一组包,使得Java开发者可以更方便地进行开发。SpringMVC是Spring的一个子项目,是一个Web框架,它基于Servlet API构建,提供了模型-视图-控制器(MVC)架构模式的实现。而MyBatis则是一个持久层框架,它提供了对象关系映射(ORM)和简化大量重复代码的API。

SSM框架的特点和优势包括:

  1. Spring提供了一个强大的容器,能够管理Java对象的创建和销毁、对象之间的依赖关系、对象的生命周期等。同时,Spring提供了诸多的企业级开发功能模块,如事务管理、安全、缓存、邮件、调度等。

  2. SpringMVC框架提供了简单易用的MVC模式,使得Web应用程序的开发变得更加简单和高效,并且可以轻松扩展和定制。

  3. MyBatis框架提供了强大的SQL映射功能,能够自动将Java对象与数据库关系映射起来,使得编写数据库访问代码时更加简单和高效,并且可以有效避免SQL注入等风险。

  4. SSM框架的整合使得三个框架之间可以相互配合,减少了各自框架间的重复代码。在实际的开发过程中,这一点显然可以大大提高效率和降低开发难度。

  5. SSM框架采用的是轻量级的开发方式,独立性强、易于扩展与维护,在开发互联网应用时表现非常优越。

  6. 其中SSM框架中的Spring框架负责IoC(Inversion of Control,控制反转)AOP(Aspect-Oriented Programming,面向切面编程),SpringMVC框架负责MVC(Model-View-Controller,模型-视图-控制器)的实现,而MyBatis框架负责数据库持久化。

    解耦是指将一个系统的不同组成部分互相分离,从而降低它们之间的依赖性。在SSM框架中,解耦可以通过以下几种方式实现:

    • 通过IoC实现解耦:Spring框架通过IoC容器来管理Bean的创建和依赖注入,将对象的创建和依赖关系的维护交给容器处理。这样,不同的组件之间可以通过容器来解耦,减少直接的依赖关系。

    • 通过AOP实现解耦:Spring框架的AOP功能可以实现横切关注点的模块化,将跨越不同模块的通用功能进行抽象,并将其注入到系统中的不同模块中。这样,不同的模块之间可以通过共享的横切关注点来解耦。

    • 通过分层实现解耦:SSM框架中的SpringMVC框架使用了MVC的分层结构,将应用程序拆分成模型(Model)、视图(View)和控制器(Controller)三个独立的组件。这样,在应用程序的不同层次中,可以通过明确的接口和约定来定义它们之间的交互,从而实现解耦。

    • 使用MyBatis实现解耦:MyBatis是一个对象关系映射(ORM)框架,它将数据库访问的逻辑与业务逻辑分离开来。开发人员通过配置映射文件,将数据库表和Java对象进行映射,从而实现数据库访问的解耦。

    通过以上的方式,SSM框架可以在不同的组件和层次之间实现解耦,提高代码的可维护性、可测试性和可扩展性。同时,解耦还可以使得团队中的不同成员可以并行开发不同的模块,提升开发效率。

总的来说,SSM框架的诞生使得Java Web应用程序的整合变得相对容易,实现了Java框架的无缝整合,使得Java Web应用开发不再依赖于冗长的XML配置和过于复杂的设计结构,具有易用,高效,可维护性的特点。

注:SSM框架默认情况不支持注解开发

框架

框架(Framework)是一个为了实现特定类型应用或解决特定问题而提供了基础结构和功能的软件工具集合。它定义了一组规范、模式和设计原则,以便开发人员可以更高效地构建应用程序。

框架通常包括以下几个方面的内容:

  1. 结构和架构:框架提供了一种组织和管理代码的结构和架构,将应用程序划分为不同的模块和组件,明确了它们之间的关系和作用。

  2. 核心库和API:框架提供了一组核心库和API,包括数据处理、网络通信、安全、缓存、事务管理等功能,开发人员可以直接调用和使用这些功能,而无需从头编写代码。

  3. 设计模式:框架通常遵循一些被验证有效的设计模式,例如MVC模式、观察者模式、工厂模式等,这些模式可以帮助开发人员构建可扩展、可维护和可重用的应用程序。

  4. 工具和辅助功能:框架通常提供了一系列工具和辅助功能,如代码生成器、调试工具、集成开发环境(IDE)插件等,以提高开发效率和便捷性。

使用框架的好处包括:

  1. 提高开发效率:框架提供了现成的基础结构和功能,可以节省开发人员编写重复代码的时间和精力,快速搭建应用程序。

  2. 标准化和规范化:框架定义了一套标准和规范,使得不同开发人员之间可以更好地合作和理解,降低项目的风险和复杂度。

  3. 提升质量和可维护性:框架通常经过大量的测试和实践,在实际应用中具有良好的性能、可靠性和稳定性,也易于维护和调试。

  4. 社区支持和生态系统:流行的框架通常有庞大的用户社区和丰富的生态系统,开发人员可以从中获取支持、学习经验和共享资源。

不同的框架适用于不同的应用场景,开发人员需要根据项目需求和自身经验选择合适的框架。常见的框架包括前端框架(如React、Angular、Vue.js)、后端框架(如Spring、Django、Ruby on Rails)、测试框架(如JUnit、Selenium)等。

Bean管理

在Spring框架中,Bean管理是指Spring容器对Java对象(也称为Bean)的创建、配置和生命周期的管理。通过Spring的Bean管理,我们可以集中管理应用程序中的对象,并通过依赖注入和面向接口编程等特性实现松耦合和可扩展的应用。

下面是一些关于Spring的Bean管理的重要概念和功能:

  1. IoC(Inverse of Control,控制反转):IoC是Spring的核心概念之一,它实现了对Bean的创建和配置的控制反转。简单来说,控制权由应用代码转移到了Spring容器,使得容器负责管理对象的创建和依赖注入。通过IoC实现了松耦合、可测试和可扩展的应用。

  2. Bean定义:Bean定义是Spring中的核心概念,它描述了在Spring容器中注册的Bean的配置信息,包括Bean的类型、属性、依赖关系等。Bean定义通常使用XML配置文件、注解或Java代码进行声明。

  3. Bean实例化:当Spring容器启动时,它根据Bean定义来实例化Bean对象。Spring支持多种实例化方式,包括使用构造函数、工厂方法、静态工厂等。

  4. Bean的作用域:Spring中的Bean的作用域定义了Bean实例的生命周期和可见范围。常见的作用域包括单例(Singleton)、原型(Prototype)、会话(Session)等。通过设置不同的作用域,可以控制Bean的生命周期和多实例等行为。

  5. 依赖注入(DI,Dependency Injection):依赖注入是Spring的另一个核心概念,它通过容器自动将依赖关系注入到对象中,而不是由对象自己创建或查找依赖。Spring支持构造函数注入、属性注入和方法注入等方式来实现依赖注入。

  6. AOP(Aspect-Oriented Programming,面向切面编程):通过AOP,可以将与业务逻辑无关的横切关注点(如日志、事务管理、安全等)从应用代码中分离出来,通过代理和切面等技术将其织入到应用程序中。Spring框架提供了强大的AOP支持,可以通过配置和注解来实现面向切面编程。

这些是Spring中Bean管理的一些重要概念和功能。通过合理使用Spring的Bean管理,可以简化开发、提高代码的可维护性和可测试性。

Spring

Spring是一个开源的Java应用程序框架,用于构建企业级应用程序。它提供了一种轻量级、非侵入式的编程模型,通过依赖注入(DI)和面向切面编程(AOP)等核心特性,可以简化Java开发的复杂性。

注:Spring容器也被称之为IoC容器

Spring框架的主要特点包括:

  1. IoC容器:Spring使用IoC容器来管理和组织应用程序中的对象。通过IoC容器,Spring可以负责创建、装配和管理对象之间的依赖关系,减轻了开发人员手动管理对象的负担。

  2. 依赖注入(DI):Spring通过依赖注入的机制,将对象的依赖关系从代码中抽离出来,并通过配置文件或注解的方式,将依赖关系注入到对象中。这样可以实现松耦合,便于维护和测试。

  3. 面向切面编程(AOP):Spring支持面向切面编程,通过AOP可以将与业务逻辑无关的横切关注点(如日志、事务管理等)进行模块化,减少重复代码的编写。

  4. 声明式事务管理:Spring提供了声明式事务管理的支持,可以通过注解或XML配置来管理事务,简化了编写和管理事务代码的过程

  5. 统一的数据访问:Spring提供了对不同持久化框架(如JDBC、Hibernate、MyBatis等)的支持,可以通过统一的接口进行数据访问,提高了代码的灵活性和可维护性。

  6. 简化开发:Spring提供了一系列的开发工具和集成支持,例如Spring MVC用于构建Web应用程序、Spring Security用于安全认证和授权等,简化了开发过程。

Spring框架的模块化设计使得它可以根据项目需求进行选择和使用,可以灵活地集成到不同的应用程序中。通过使用Spring框架,开发人员可以更高效地开发Java应用程序,提高代码的质量和可维护性。

配置bean.xml文件

在某些框架中,如Spring框架,可以使用bean.xml文件进行项目内容的配置。bean.xml文件是一个XML配置文件,用于定义和组织应用程序中的各个组件(也称为bean)以及它们之间的依赖关系。

以下是一个示例bean.xml文件的基本结构:

<?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">

    <!-- 定义Bean -->
    <bean id="myBean" class="com.example.MyBean">
        <!-- 设置属性值 -->
        <property name="propertyName" value="propertyValue" />
    </bean>

    <!-- 定义其他Bean -->
    <!-- ... -->

</beans>

在这个示例中,beans标签是根标签,它包含了所有的Bean定义。beans标签使用了命名空间并指定了XML模式文档的位置。

在bean标签中,id属性用于指定Bean的唯一标识符class属性用于指定Bean的类名。在bean标签的内部,你可以定义Bean的属性值,可以使用property标签为Bean设置属性。其中,name属性用于指定属性名,value属性用于指定属性值。

通过将应用程序中的各个组件定义为Bean,并使用bean.xml文件进行配置,可以实现松耦合、可重用和可维护的应用程序。在实际开发中,bean.xml文件还可以包含其他配置,如数据源、AOP配置、事务管理等。

需要注意的是,每个框架的配置方式可能有所不同,bean.xml只是Spring框架中一种常见的配置方式。开发人员应了解框架的配置规则和建议,根据实际情况进行适当的配置。

创建对象

在Spring框架中,可以使用不同的方式创建对象,可以分为以下几种:

  1. 在 Spring 中,可以使用配置文件来创建对象,以下是几种常见的方式:

    1. 使用默认构造函数创建对象

      通过<bean>标签的class属性指定对象的类名,Spring容器在初始化时实例化对象并调用默认构造函数初始化对象。

      <bean id="person" class="com.example.Person" />
      
    2. 使用有参构造函数创建对象

      可以使用<constructor-arg>标签在<bean>标签内指定构造函数的参数,并传递到构造函数中。

      <bean id="person" class="com.hqyj.lxh.pojo.Person">
      <!--constructor-arg标签 通过有参构造        -->
              <constructor-arg name="personAge" value="18"/>
              <constructor-arg name="personName" value="张三"/>
          </bean>
          <!--基于index属性 根据有参构造中参数索引来赋值        -->
      <bean id="person1" class="com.hqyj.lxh.pojo.Person">
          <constructor-arg index="0" value="李四"/>
          <constructor-arg index="1" value="19"/>
      
      
      </bean>
      
      <!--    基于type属性-->
          <bean id="person2" class="com.hqyj.lxh.pojo.Person">
              <constructor-arg type="java.lang.String" value="王五"/>
              <constructor-arg type="int" value="20"/>
          </bean>
      

      在上述配置文件中,展示了三种不同的方式来创建带有参数的对象:

      1. 使用<constructor-arg>标签,并通过name属性指定参数名称来赋值。例如,在<bean>标签中,通过<constructor-arg name="personAge" value="18"/>personAge参数赋值为18,给personName参数赋值为"张三"。
      2. 使用<constructor-arg>标签,并通过index属性指定参数的索引来赋值。用于根据有参构造函数中参数的顺序进行赋值。例如,在<bean>标签中,通过<constructor-arg index="0" value="李四"/>给第一个参数赋值为"李四",通过<constructor-arg index="1" value="19"/>给第二个参数赋值为19。
      3. 使用<constructor-arg>标签,并通过type属性指定参数的类型来赋值。通过指定参数类型来判断赋值给哪个参数。例如,在<bean>标签中,通过<constructor-arg type="java.lang.String" value="王五"/>给参数类型为java.lang.String的参数赋值为"王五",通过<constructor-arg type="int" value="20"/>给参数类型为int的参数赋值为20。

      这些配置方式可以根据你的实际需求选择使用,根据参数的名称、索引或类型来赋值给构造函数的参数。使用适当的方式可以确保正确创建对象并传递所需的参数。 -->

      <bean id="person" class="com.example.Person">
          <constructor-arg value="John" />
          <constructor-arg value="Doe" />
      </bean>
      

      p标签注入

      在 Spring 中,可以使用p命名空间注入属性值到 Bean 中。使用p命名空间可以使配置文件更简洁,不需要显式地使用 <property> 标签。

      首先,确保在 XML 配置文件的 beans 根标签中添加命名空间声明:

      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:p="http://www.springframework.org/schema/p"
             ...>
      

      然后,可以在 <bean> 标签中使用 p 命名空间来设置属性值。例如:

      <bean id="person" class="com.example.Person"
            p:firstName="John"
            p:lastName="Doe"
            p:age="25" />
      

      在上面的示例中,person Bean 的类为 com.example.Person,并通过 p 命名空间注入了 firstNamelastNameage 属性的值。

      注意事项:

      • 使用 p 命名空间注入属性值时,属性名称需要使用驼峰命名规则,如 firstNamelastName
      • 如果属性值是字符串类型,可以直接在值的两边加引号,如 p:firstName="John"
      • 如果属性值是其他类型(如整数、布尔值等),可以直接写属性值,如 p:age="25"

      使用p命名空间可以简化配置文件,但请确保目标 Bean 中有相应的属性,并且属性的名称与配置一致。

    3. 使用静态工厂方法创建对象

      通过<bean>标签指定class属性为静态工厂类名,factory-method属性指定需要调用的静态工厂方法名。

      <bean id="person" class="com.example.PersonFactory" factory-method="createPerson" />
      
    4. 使用实例工厂方法创建对象

      首先创建工厂对象并配置,<bean>标签的class属性指定工厂类名,然后再通过<bean>标签定义需要创建的对象并指定class属性,factory-bean属性指定工厂对象实例的名称,factory-method属性指定工厂方法名。

      <bean id="personFactory" class="com.example.PersonFactory" />
      
      <bean id="person" factory-bean="personFactory" factory-method="createPerson" />
      

在Spring框架中,对象的创建和管理由IoC容器来负责,我们只需要在配置文件或Java类中声明Bean,然后由IoC容器进行实例化、装配和管理。因此,使用Spring框架可以极大地简化对象创建和管理的工作量,提高代码的可维护性和重用性。

以下是Spring默认情况单例模式管理bean:

public class UserTest {
    public static void main(String[] args) {
        //1.读取bean.xml配置文件,加载配置文件的内容
        ApplicationContext ac=new ClassPathXmlApplicationContext("classpath:config/bean.xml");
        //classpath:路径从编译之后的class文件进行计算
        //2.通过ApplicationContext对象,访问配置我呢间中配置的对象,通过对象名字进行访问,对象的名字=bean标签的id
        //getBean 方法 参数一对象的名字 参数儿为可选参数
        //User user=(User)ac.getBean("user");
        User user = ac.getBean("user", User.class);
        System.out.println(user);
        user.show();
        User user1 = ac.getBean("user", User.class);
        System.out.println(user==user1);
    }
}

根据你提供的代码,输出结果应该是true

这是因为默认情况下,Spring的ApplicationContext使用单例模式管理bean。也就是说,当使用getBean方法获取同一个名为user的bean时,Spring容器会返回同一个实例。

所以,useruser1引用的是同一个User实例,因此它们比较的结果是true

如果你希望每次调用getBean方法时都返回一个新的实例,可以在bean.xml配置文件中将user的作用域声明为原型(prototype)。可以通过在bean元素中添加scope="prototype"来实现,例如:

<bean id="user" class="com.example.User" scope="prototype">
    <!-- 更多配置 -->
</bean>

这样配置后,每次调用getBean方法时都会返回一个新的User实例,useruser1将不再引用同一个实例,输出结果将会是false

在 Spring 中,Bean 的作用域(Scope)可以控制 Bean 实例的创建和销毁时机

Spring 提供了以下五种作用域:

  1. singleton默认):在整个应用程序中只有一个共享 Bean 实例,即每次访问它都会得到同一个 Bean 实例。
  2. prototype每次请求都会创建一个新的 Bean 实例
  3. request:在每个 HTTP 请求中,都会创建一个新的 Bean 实例。该作用域仅在使用 web-aware ApplicationContext 时才适用。
  4. session:在每个 HTTP session 中,都会创建一个新的 Bean 实例。该作用域仅在使用 web-aware ApplicationContext 时才适用。
  5. globalSession:在一个全局的 HTTP session 中,共享一个 Bean 实例。该作用域仅在使用 web-aware ApplicationContext 时才适用。

下面是一个示例,其中 singletonprototype 是其中两个最常见的作用域。

<bean id="mysingletonbean" class="com.example.SingletonBean" scope="singleton" />

<bean id="myprototypebean" class="com.example.PrototypeBean" scope="prototype" />

在这个示例中,mysingletonbean 的作用域是 singleton它将在 Spring 容器启动时创建一个 Bean 实例,并在应用程序生命周期内共享这个实例。而 myprototypebean 的作用域是 prototype,它将在每次调用时创建一个新的 Bean 实例。

需要注意的是,使用作用域 prototype 可能会导致内存泄漏问题。**因为每次请求都会创建一个新的 Bean 实例,如果没有正确使用和销毁这些实例,会导致内存泄漏。**因此,使用 prototype 作用域时应特别小心,确保正确地管理 Bean 实例的生命周期。

懒加载机制

懒加载(Lazy Loading)是一种延迟加载的机制,它使得在需要使用时才创建对象或加载资源,而不是在启动时就提前加载。

在Spring中,默认情况下,容器在启动时会实例化所有单例作用域的bean,并将其放入容器中。这意味着在启动过程中会创建所有单例bean的实例。

然而,通过懒加载机制,我们可以延迟bean的实例化,在真正需要使用时才进行创建。

在Spring中,可以通过在配置文件中设置lazy-init="true"来启用懒加载。例如:

<bean id="user" class="com.example.User" lazy-init="true">
    <!-- 更多配置 -->
</bean>

通过这个配置,当容器启动时,不会立即实例化user的 bean。只有当第一次调用getBean("user")方法时,才会创建User实例并且返回

使用懒加载机制可以提高启动速度和内存使用效率,特别是当有很多大对象需要实例化时,或者对象的创建成本较高的情况下。它允许我们在真正需要使用bean之前,将资源和计算延迟到最后可能的时刻。

需要注意的是,懒加载只适用于单例作用域的bean。对于其他作用域(如原型、会话等),懒加载不生效,容器仍会在启动时实例化这些bean。

IOC

IoC(Inversion of Control,控制反转)是Spring框架的核心概念之一

控制反转指的是将对象的创建和依赖关系的管理从应用程序代码中转移到了框架(比如Spring容器)中。在传统的开发模式中,应用程序代码通常负责创建和管理对象的生命周期以及它们之间的依赖关系。而在IoC模式下,框架接管了对象的创建和依赖关系的管理,将控制权反转给了框架。

在Spring中,IoC由Spring容器来实现。Spring容器负责实例化对象、处理对象的依赖关系并将依赖注入到对象中。通过IoC,我们可以实现对象之间的松耦合,将对象的创建和配置与应用程序逻辑分离,使得应用程序更加灵活和可扩展。

当使用Spring的IoC容器时,我们需要先定义Bean的配置信息,通常使用XML配置文件、注解或Java代码进行声明。这些配置信息告诉Spring容器如何实例化Bean、处理Bean之间的依赖关系以及在何处注入这些依赖。

Spring容器在启动时会读取这些配置信息,并根据配置创建和管理对象。应用程序代码只需要从容器中获取所需的Bean,而不需要关心如何创建和配置这些对象,也不需要手动处理对象之间的依赖关系。

通过IoC,Spring提供了以下好处:

  1. 松耦合:应用程序代码只依赖于抽象接口而不依赖具体实现类,从而减少了对象之间的紧耦合,使得应用程序更加灵活、可扩展和可维护。

  2. 可测试性:由于通过依赖注入将对象的依赖关系外部化,方便了对对象的测试和模拟,提高了代码的可测试性。

  3. 可扩展性:通过配置方式来管理对象的依赖关系,可以方便地增加、替换或修改Bean的实例化和依赖关系配置,从而实现代码的可扩展性。

Spring框架提供了多种实现IoC的方式,包括XML配置、注解、Java配置等。开发人员可以根据项目需求和个人偏好来选择合适的方式来实现IoC。

依赖注入

依赖注入(Dependency Injection,DI)是Spring框架的另一个核心概念,它是实现IOC的一个重要手段。

依赖注入指的是通过注入依赖来创建对象,而不是由对象自行创建或查找依赖。在依赖注入模式下,对象不需要知道如何获取它的依赖,而是由容器在对象实例化时将其依赖自动注入到对象中。

在Spring中,容器负责处理依赖注入。当容器实例化一个对象时,它会检查对象的依赖关系,并将依赖对象自动注入到对象中。依赖注入可以通过构造函数注入、Setter方法注入、接口注入等方式来实现。

下面是依赖注入的一些常见方式:

  1. 构造函数注入(Constructor Injection):通过类的构造方法完成依赖注入。
public class Employee {
    private Address address;

    public Employee(Address address) {
        this.address = address;
    }

    // getter and setter methods
}

public class Address {
    // address properties
}
  1. Setter方法注入(Setter Injection):通过对象的Setter方法完成依赖注入。
public class Employee {
    private Address address;

    public void setAddress(Address address) {
        this.address = address;
    }

    // getter methods
}

public class Address {
    // address properties
}
  1. 接口注入(Interface Injection):通过实现接口来完成依赖注入。
public interface EmployeeService {
    void setEmployeeDao(EmployeeDao employeeDao);
}

public class EmployeeServiceImpl implements EmployeeService {
    private EmployeeDao employeeDao;

    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }

    // service methods
}

public class EmployeeDaoImpl implements EmployeeDao {
    // dao methods
}

通过依赖注入,我们可以实现以下好处:

  1. 解耦:依赖注入可以将对象与它的依赖解耦,使得对象更容易独立测试和维护。

  2. 易于扩展:当需要替换依赖时,只需要用新的实现替换原有的实现,而不需要修改对象的代码。

  3. 提高重用性:依赖注入可以使得依赖关系更加明确,方便了对象的重用和组合。

Spring框架支持多种依赖注入方式,包括XML配置、注解、Java配置等。开发人员可以根据项目需求和个人偏好来选择合适的方式来实现依赖注入。

基于注解的方式实现IOC

基于注解的方式实现 IoC(控制反转)可以简化 Spring 配置文件的编写,提高开发效率。下面是一些常用的注解及其用法:

  1. @Component:将类标记为 Spring 组件,让 Spring 自动扫描并将其初始化为 Bean。
  2. @Autowired:自动装配依赖,将 Bean 注入到类的属性、构造函数或方法中。
  3. @Qualifier:在有多个相同类型的 Bean 时,指定具体要注入的 Bean。
  4. @Value:给属性赋值,支持从配置文件中读取。
  5. @Configuration:将类标记为配置类,可以在类中定义 Bean。
  6. @Bean:在配置类中用于声明一个 Bean。
  7. @Scope:定义 Bean 的作用域,如单例(Singleton)或原型(Prototype)。

下面是一个示例,展示如何使用注解来实现 IoC:

@Component
public class Animal {
    @Autowired
    private Cat cat;

    public void makeSound() {
        System.out.println("The cat named " + cat.getName() + " is making sound.");
    }
}

@Component
public class Cat {
    @Value("Tom")
    private String name;

    public String getName() {
        return name;
    }
}

@Configuration
public class AppConfig {
    @Bean
    public Animal animal() {
        return new Animal();
    }

    @Bean
    public Cat cat() {
        return new Cat();
    }
}

在上述示例中,Animal 类使用了 @Autowired 注解将 Cat 注入到 cat 属性中。Cat 类使用了 @Value 注解将属性 name 的值设置为 “Tom”。AppConfig 类使用了 @Configuration 注解将其标记为配置类,并使用 @Bean 注解声明了 AnimalCat 的 Bean。

在主程序中,你可以使用 Spring 的上下文来获取这些 Bean,并调用它们的相关方法:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        Animal animal = context.getBean(Animal.class);
        animal.makeSound();
    }
}

当你运行这个程序时,你将会看到输出 “The cat named Tom is making sound.”,表示注入和调用成功。

注意,使用注解方式实现 IoC 需要确保以下几点:

  • 在主程序中使用 AnnotationConfigApplicationContext 或类似的注解驱动的上下文来加载配置类。(可以使用 @Import 注解导入其他配置类)
  • 确保被扫描的组件和配置类包含在 @ComponentScan 注解标记的包中。
  • 在需要使用自动装配的地方使用 @Autowired 注解。
  • 在需要配置的地方使用 @Value@Bean 等注解。
  • 在主程序中使用 getBean() 方法来获取 Bean,或者使用注解标记对应的属性、构造函数或方法。
常用接口

Spring 框架中有许多常用的注解,用于实现不同的功能和配置:

把当前修饰的类注入到IOC容器中

  1. @Component:用于标记一个类作为 Spring 组件,让 Spring 自动扫描和创建实例。
  2. @Controller:用于标记一个类作为 Spring MVC 的控制器。
  3. @Service:用于标记一个类作为服务层的组件。
  4. @Repository:用于标记一个类作为数据访问层(如 DAO)的组件。
  5. @Autowired:自动装配依赖,可以用在构造函数、属性和方法上。
  6. @Qualifier:在存在多个相同类型的 Bean 时,通过名称或标识符指定具体要注入的 Bean。
  7. @Value:给属性赋值,支持从配置文件中读取。
  8. @Configuration:用于标记一个类作为配置类,可以定义 Bean 和其他组件。
  9. @Bean:在配置类中用于声明一个 Bean。
  10. @Scope:用于指定 Bean 的作用域,如 singleton(单例)或 prototype(原型)。
  11. @RequestMapping:用于映射请求路径到控制器的处理方法上。
  12. @PathVariable:用于获取请求路径中的变量值。
  13. @RequestParam:用于获取请求参数的值。
  14. @ResponseBody:用于将方法的返回值直接作为响应体返回给客户端。
  15. @ExceptionHandler:用于定义全局的异常处理方法。
  16. @Transactional:用于标记一个方法或类进行事务管理。

以上只是一些常用的 Spring 注解,Spring 框架还有更多的注解可以用于不同的场景和需求。

基于全注解

Spring提供了多种方式来使用全注解的方式创建对象。下面列举了几种常见的方法:

  1. @Component注解:使用@Component注解标记一个类,表示这是一个组件,Spring会自动扫描并将其实例化为一个Bean。例如:
@Component
public class MyComponent {
    // ...
}
  1. @Service注解:使用@Service注解标记一个类,表示这是一个服务类,通常用于业务逻辑的处理。与@Component注解类似,也会被自动扫描并实例化为一个Bean。例如:
@Service
public class MyService {
    // ...
}
  1. @Repository注解:使用@Repository注解标记一个类,表示这是一个数据访问类,通常用于数据库访问操作。同样会被自动扫描并实例化为一个Bean。例如:
@Repository
public class MyRepository {
    // ...
}
  1. @Controller注解:使用@Controller注解标记一个类,表示这是一个控制器,用于处理Web请求。同样也会被自动扫描并实例化为一个Bean。例如:
@Controller
public class MyController {
    // ...
}

在使用上述注解时,需要确保已经开启了组件扫描,可以通过在配置类上使用@ComponentScan注解来配置扫描的包路径。例如:

@Configuration
@ComponentScan("com.example")
public class AppConfig {
    // ...
}

上述代码将扫描com.example包及其子包下的所有带有@Component注解的类,并将其实例化为Spring的Bean。

除了使用上述注解之外,还可以使用@Autowired注解来进行依赖注入,以获取其他Bean的实例。例如:

@Service
public class MyService {
    private final MyRepository repository;

    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }

    // ...
}

上述代码中,通过@Autowired注解将 MyRepository注入到 MyService中。

通过使用这些注解,可以更加方便地使用全注解方式创建对象,并使它们成为Spring容器的管理对象。这样可以简化配置,提高开发效率。

属性注入注解

在Spring中,有多个属性注入的注解可以使用。下面是一些常见的属性注入注解:

  1. @Autowired可以用于自动完成依赖注入。它可以标记在构造方法、字段、或者方法上。当Spring容器启动时,它会自动查找匹配的依赖,并将其注入到被标注的属性中。

    如果要实现自动装配,那么必须满足两个类的对象都存在于IOC中

    例如:

@Service
public class MyService {
    private MyRepository repository;

    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }

    // ...
}
  1. @Value:用于注入简单属性值。它可以标记在字段、方法参数或者方法返回值上。通过@Value注解,可以将一个属性值直接注入到标注的位置。例如:
@Service
public class MyService {
    @Value("example.property")
    private String someProperty;

    // ...
}
  1. @Resource 是 Java EE 5 提出的注解,而在 Java SE 6 中便被支持。它是一种 Java 注解,作为 Java Bean 技术的补充,用于对 Java 对象(例如 bean)进行注解,指明要注入的实例或者是提供实例。和 @Autowired@Qualifier 相似,@Resource 也是一种注解实现依赖注入(DI)的方式。

    具体来说,@Resource 注解的作用是将指定的名称的 Bean 注入到使用该注解的变量中。它的用法与 @Autowired@Qualifier 注解类似,都是直接注解在需要注入 Bean 的属性、构造函数、方法、参数或类上。

    不过,@Resource 注解有一点与其他两个注解不同,在使用时可以指定名称和类型信息,也就是说,它既可以根据名称进行自动装配,也可以根据类型进行自动装配。具体例子如下:

    public class UserServiceImpl implements UserService {
        // 根据名称进行装配
        @Resource(name = "userRepository")
        private UserRepository userRepository;
    
        // 根据类型进行装配
        @Resource
        private OrderRepository orderRepository;
    
        // ...
    }
    

    在这里,@Resource(name = "userRepository") 可以让 Spring 框架根据名为 “userRepository” 的 Bean 进行自动装配。而 @Resource 注解不带参数时,Spring 框架会根据需要注入的属性的类型查找合适的 Bean 进行自动装配。

    需要注意的是,@Resource 注解只有一个属性 name,表示要注入的 Bean 的名称,如果不设置该属性,那么默认使用属性名或者字段名作为 Bean 的名称进行注入。而 @Autowired@Qualifier 支持更为灵活的装配方式,例如根据类型、名称、自定义注解等多种方式进行限定。

    总的来说,@Resource 注解是一种基于名称和类型进行自动装配的方式,用于取代 Spring 之前的 J2EE 规范中的 EJB 注入方式。不过它的功能相对比较简单,不如 @Autowired 以及 @Qualifier 等注解实用。

4.@Inject:与@Autowired注解类似,@Inject注解也可以用于自动完成依赖注入,其功能和用法几乎相同。例如:

@Service
public class MyService {
    private MyRepository repository;

    @Inject
    public MyService(MyRepository repository) {
        this.repository = repository;
    }

    // ...
}

5.@Qualifier 是 Spring 框架提供的一个注解,用于根据名称或者其他条件进行限定自动装配的 Bean。

在使用自动装配时,如果有多个 Bean 映射到同一类型的话,Spring 就会抛出 NoUniqueBeanDefinitionException 异常。这时,我们可以通过 @Qualifier 注解结合名称来识别特定的 Bean 进行自动装配。

例如,假设我们有两个实现了 UserRepository 接口的 Bean:UserJdbcRepository 和 UserJpaRepository,如下所示:

@Repository
public class UserJdbcRepository implements UserRepository {
    // ...
}

@Repository
public class UserJpaRepository implements UserRepository {
    // ...
}

如果我们用 @Autowired 注解直接注入,就会抛出 NoUniqueBeanDefinitionException 异常:

@Autowired
private UserRepository userRepository; // 抛出异常:NoUniqueBeanDefinitionException

此时,我们就可以使用 @Qualifier 注解指定想要注入的 Bean:

@Autowired
@Qualifier("userJpaRepository")
private UserRepository userRepository;

上面的例子中,@Qualifier("userJpaRepository") 限定了自动装配的 Bean 为 UserJpaRepository,可以解决多个 Bean 映射到同一类型的问题。

除了使用名称,@Qualifier 还可以结合自定义的注解进行使用。例如,我们定义一个自定义的注解,标记我们需要注入的 Bean:

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface UserRepoType {
    RepoType value();
}

然后在实现 UserRepository 接口的 Bean 上使用该注解:

@Repository
@UserRepoType(RepoType.JPA)
public class UserJpaRepository implements UserRepository {
    // ...
}

@Repository
@UserRepoType(RepoType.JDBC)
public class UserJdbcRepository implements UserRepository {
    // ...
}

最后,在注入的时候使用 @Qualifier 注解指定要注入的 Bean 的类型:

@Autowired
@UserRepoType(RepoType.JPA)
private UserRepository userRepository;

这样,就可以根据自定义的注解进行限定自动装配的 Bean。

总之@Qualifier 注解是 Spring 框架提供的一种快捷指定 Bean 引用的方式,可以根据名称或自定义注解等来限定自动注入的 Bean。

AOP

AOP(面向切面编程)是一种编程范式,它通过将横切关注点(如日志记录、事务管理等)从业务逻辑中剥离出来,以增强代码的可重用性、可维护性和可扩展性。

在传统的面向对象编程中,业务逻辑代码通常存在于多个对象的方法中,而横切关注点(如日志记录、事务管理等)则通过代码复制或重复粘贴的方式出现在多个方法中,导致代码重复和维护困难。

AOP 的思想是将横切关注点模块化,并将其植入到现有代码中,而无需修改原始代码。这样一来,业务逻辑代码与横切关注点代码可以更好地解耦,提高了代码的模块化程度和可维护性。

在 Java 中,AOP 的实现通常使用切面、连接点、切点和通知等概念:

  • 切面(Aspect):横切关注点的模块化。它包含了要在业务逻辑中植入的代码(通常称为通知)以及定义了何时何地进行植入的切点。
  • 连接点(Join Point):在代码中可能被植入切面的位置。例如,方法调用、方法执行、异常抛出等。
  • 切点(Pointcut):定义了哪些连接点被包含在切面中。切点通过表达式或正则表达式来描述连接点的匹配规则。
  • 通知(Advice):切面植入到连接点的代码。通常定义了在连接点执行前、执行后或发生异常时要执行的代码。

Spring Framework 提供了强大的 AOP 支持,通过使用 Spring AOP,您可以通过配置方式或使用注解来定义切面和通知,并将其应用于目标方法。

通过 AOP,您可以在不修改原始业务逻辑代码的情况下,实现诸如日志记录、性能监测、事务管理等横切关注点的功能。

动态代理

动态代理是一种在运行时生成代理对象的技术,可以用于实现 AOP(面向切面编程),以便在不修改原始对象的情况下,向原始对象植入额外的行为。

在 Java 中,动态代理通常使用 Java 的反射机制来实现。有两种主要的动态代理方式:

  1. JDK 动态代理:该方式是通过 Java 提供的 java.lang.reflect.Proxy 类实现的。为了创建代理对象,需要定义一个接口,并为接口提供一个实现类(真实对象)和一个代理类。代理类实现了 InvocationHandler 接口,它提供了一个 invoke() 方法,用于在调用代理对象方法时执行额外的逻辑。通过 Proxy.newProxyInstance() 方法,可以通过接口、真实对象和代理类的实例创建代理对象。

  2. CGLIB 动态代理:该方式是通过第三方库(例如 CGLIB)生成代理对象的子类。这种方式适用于没有接口的类。代理类继承原始类,并重写了原始类中的方法,以便在执行代理对象方法时执行额外的逻辑。通过 CGLIB 提供的 Enhancer 类,可以创建代理对象。

动态代理可以帮助您实现横切关注点的功能,例如日志记录、事务管理、性能监测等。它将原始对象和代理对象解耦,并在运行时生成代理对象来包装原始对象。

需要注意的是,动态代理通常基于接口进行代理,因此原始对象必须实现一个或多个接口。如果原始对象没有实现任何接口,则只能使用 CGLIB 动态代理。

JDK代理

JDK 动态代理是 Java 提供的一种实现动态代理的机制。它是基于接口的代理,通过反射和代理类在运行时生成代理对象。

使用 JDK 动态代理,您需要以下步骤:

  1. 定义一个接口:首先,您需要定义一个接口,该接口是您要代理的类的公共方法的集合。
public interface MyInterface {
    void myMethod();
    // 其他方法...
}
  1. 实现业务逻辑:您需要编写一个实现类,该类实现了接口中的方法,这是真正执行业务逻辑的类。
public class MyImplement implements MyInterface {
    public void myMethod() {
        // 实现业务逻辑
    }
    // 其他方法的实现...
}
  1. 编写代理逻辑:您需要编写一个代理类,该类实现了 InvocationHandler 接口,并在 invoke() 方法中实现代理逻辑。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用真实对象方法前执行的逻辑
        System.out.println("Before invoking myMethod...");

        // 调用真实对象的方法
        Object result = method.invoke(target, args);

        // 在调用真实对象方法后执行的逻辑
        System.out.println("After invoking myMethod...");

        return result;
    }
}
  1. 创建代理对象:使用 Proxy.newProxyInstance() 方法创建代理对象。
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        MyInterface target = new MyImplement();
        MyInvocationHandler invocationHandler = new MyInvocationHandler(target);

        MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            invocationHandler
        );

        // 通过代理对象调用方法
        proxy.myMethod();
    }
}

在上述示例中,MyInvocationHandler 类实现了 InvocationHandler 接口,并在 invoke() 方法中加入了在调用真实对象方法前后执行的逻辑。然后,通过 Proxy.newProxyInstance() 方法创建了代理对象。最后,通过代理对象调用方法时,会自动执行代理逻辑。

JDK 动态代理的一个限制是只能代理实现了接口的类。如果要代理的类没有实现任何接口,您可以考虑使用 CGLIB 动态代理。

CGLIB代理

CGLIB 动态代理是一个基于继承的代理机制。它是通过字节码技术在运行时动态生成一个子类来覆盖非 final 类型的方法,并在子类中对方法进行增强。

使用 CGLIB 动态代理,您需要以下步骤:

  1. 添加依赖:首先,您需要添加 CGLIB 的依赖:
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
  1. 定义一个类:您需要定义一个类,该类包含您要增强的方法。
public class MyClass {
    public void myMethod() {
        // 具体的业务逻辑
    }
}
  1. 编写代理逻辑:您需要编写一个代理类,该类扩展了 MethodInterceptor 接口,并在 intercept() 方法中实现代理逻辑。
import net.sf.cglib.proxy.*;

public class MyInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 在调用真实对象方法前执行的逻辑
        System.out.println("Before invoking myMethod...");

        // 调用真实对象的方法
        Object result = proxy.invokeSuper(obj, args);

        // 在调用真实对象方法后执行的逻辑
        System.out.println("After invoking myMethod...");

        return result;
    }
}
  1. 创建代理对象:使用 Enhancer.create() 方法创建代理对象。
public class Main {
    public static void main(String[] args) {
        MyInterceptor interceptor = new MyInterceptor();

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback(interceptor);

        MyClass proxy = (MyClass) enhancer.create();

        // 通过代理对象调用方法
        proxy.myMethod();
    }
}

在上述示例中,MyInterceptor 类实现了 MethodInterceptor 接口,并在 intercept() 方法中加入了在调用真实对象方法前后执行的逻辑。然后,通过 Enhancer 类动态创建代理对象。最后,通过代理对象调用方法时,会自动执行代理逻辑。

需要注意的是,基于 CGLIB 的动态代理会创建一个子类以实现代理,因此被代理的类必须是非 final 类型的。此外,由于该代理机制需要在运行时动态创建代理类,因此会产生额外的开销,对于一些大型的程序或者频繁调用的方法可能会影响性能,因此需要权衡后再使用。

术语

AOP 是面向切面编程(Aspect-Oriented Programming)的缩写,它是一种软件开发的编程范式。在传统的面向对象编程中,主要关注的是对象的层次结构和对象之间的关系。而 AOP 则是通过将横切逻辑(即不同领域的功能需求)从主要业务逻辑中分离出来来实现这一目标。

以下是一些与 AOP 相关的术语:

  1. 切面(Aspect):切面是横切关注点(即横跨多个对象或模块的功能需求)的模块化。它通常定义了在目标对象的方法执行前、执行后、抛出异常等时机需要执行的代码。

  2. 连接点(Join Point):连接点是在应用程序执行期间可以插入切面的点。比如,在方法执行时、抛出异常时等,这些都可以看作是连接点。

  3. 通知(Advice):通知是切面在连接点上执行的代码,它定义了在连接点处要执行的操作。常见的通知类型包括前置通知(Before Advice,方法执行前执行)、后置通知(After Advice,方法执行后执行)、环绕通知(Around Advice,方法执行前后都执行)、异常通知(After Throwing Advice,方法抛出异常时执行)和返回通知(After Returning Advice,方法正常返回时执行)。

  4. 切点(Pointcut):切点用于定义连接点的集合。它通过匹配连接点的方式来确定切面通知的执行时机。切点可以使用表达式或者模式来进行匹配。

  5. 引入(Introduction):引入是一种在不修改目标对象代码的情况下,向目标对象添加新的方法或属性的功能。通过引入,可以在不改变现有代码的基础上增加一些新的行为。

  6. 织入(Weaving):织入是将切面应用到目标对象中,并创建新的代理对象的过程。织入可以在编译时(AspectJ 编译器)、类加载时(通过字节码操作工具)或者运行时(动态代理)等时机实现。

AOP 可以帮助开发人员将横切关注点(如日志记录、事务管理、安全控制等)与主要业务逻辑相分离,提高代码的可复用性和可维护性。常见的 AOP 框架有 AspectJ、Spring AOP 等。

希望以上解释对您有所帮助。如果您还有其他问题,请随时提问。

切入点表达式

切入点表达式(Pointcut Expression)是在面向切面编程(AOP)中使用的一种语法,用于定义哪些连接点(Join Point)会匹配到切点(Pointcut)。

切点表达式通常由两部分组成:切点指示器和切点签名。

  1. 切点指示器:切点指示器定义了要匹配的连接点的类型或位置。它可以指示匹配类、方法、字段、异常等。常用的切点指示器包括:

    • execution:匹配方法的执行。
    • within:匹配在指定类型内部执行的方法。
    • this:匹配对象是指定类型的方法的执行。
    • target:匹配目标对象是指定类型的方法的执行。
    • args:匹配传入参数符合指定类型的方法的执行。
    • @annotation:匹配带有指定注解的方法的执行。
  2. 切点签名:切点签名用于指定被匹配方法的签名信息。它描述了要匹配的方法的特征,如方法名、参数列表、返回类型等。常见的切点签名元素包括:

    • 方法名:指定要匹配的方法名,可使用通配符。
    • 参数列表:指定要匹配的参数类型或参数列表的个数。
    • 返回类型:指定要匹配的方法的返回类型。

切入点表达式可以使用丰富的语法来精确匹配连接点。例如,可以使用运算符(与、或、非)组合多个切点指示器和切点签名条件,使用通配符来匹配模糊的方法名或包名,使用正则表达式进行更复杂的匹配等。

以下是一个示例的切入点表达式:

execution(* com.example.service.*Service.*(..))
    execution(* com.example.service.*.*(..))

该表达式匹配 com.example.service 包下所有类名以 “Service” 结尾的方法的执行。

不同的 AOP 框架可能对切入点表达式的语法有所差异,例如在 AspectJ 中使用的切入点表达式与在 Spring AOP 中使用的切入点表达式略有不同。因此,具体的切入点表达式语法还需根据所使用的 AOP 框架来确定。

希望以上解释对您有所帮助。如果您还有其他问题,请随时提问。

SpringMVC

SpringMVC 的执行流程如下

  1. 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
  2. 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
  3. DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
  4. HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
  5. Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
  6. HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
  7. DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
  8. ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
  9. DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
  10. 视图负责将结果显示到浏览器(客户端)。

Mybatis

MyBatis是一种持久层框架,它允许将 SQL 语句与 Java 对象进行映射,从而很好地解决了业务逻辑和数据库操作之间的耦合问题。MyBatis首先通过XML或注解映射器定义SQL语句,然后将它们映射为Java方法,最终执行数据库操作。MyBatis具有易于学习和使用、可定制性强、执行效率高等特点,因此被广泛用于Java web项目的开发中。

MyBatis有以下一些优点:

  1. 简单易用:MyBatis的学习和使用门槛相对较低,它使用简单且直观的XML配置文件或注解方式来映射数据对象和SQL语句,使开发者可以快速上手。

  2. 灵活性高:MyBatis提供了丰富的配置项,可以通过配置文件或注解来定制SQL语句、查询结果的映射方式、事务处理等,允许开发者灵活地根据需求进行定制。

  3. 性能优化:MyBatis的SQL语句是预编译的,可以有效减少数据访问开销。此外,MyBatis还提供了缓存机制,可将结果缓存起来,提高查询性能。

  4. 与数据库交互灵活:MyBatis可以与各种不同类型的数据库进行交互,适应不同项目的需求。

然而,MyBatis也存在一些缺点:

  1. 配置复杂:MyBatis的配置比较繁琐,需要编写大量的XML配置文件或注解,对于一些简单的查询操作,可能需要编写较多的配置代码。

  2. 开发效率相对较低:相比于像Hibernate这样的ORM框架,MyBatis需要手动编写SQL语句和进行数据库操作,开发效率相对较低。

  3. 缺乏对象关系映射:相比于全面的ORM框架,MyBatis在对象关系映射方面的支持相对较弱,需要开发者手动编写SQL。

综上所述,MyBatis在简单易用、性能优化和灵活性方面具有明显优势,但在配置复杂和开发效率方面可能有一定的劣势。开发者需要根据具体项目的需求和团队的技术水平来选择合适的持久层框架。

下面我来给您提供一个 MyBatis 实例,包括创建 employee 表,并完成查询列表、模糊查询、关键字查询等操作。

配置Mybatis

pom.xml

<!--MyBatis依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>
<!--数据库依赖-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.17</version>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--    配置驼峰命名映射-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases>
        <typeAlias type="com.hqyj.lxh.pojo.User" alias="user"/>
        <typeAlias type="com.hqyj.lxh.pojo.Employee" alias="employee"/>
    </typeAliases>
    <!--    environments:配置环境的标签-->
    <environments default="development">
        <!--        配置其中一个环境-->
        <environment id="development">

            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--                驱动-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--                连接地址-->
                <property name="url" value="jdbc:mysql://localhost:3306/j230901ssm?useUnicode=true&amp;characterEncoding=utf8"/>
                <!--                数据库账号-->
                <property name="username" value="root"/>
                <!--                -->
                <property name="password" value="lixihao011124"/>
            </dataSource>
        </environment>
    </environments>
    <!--    mappers:映射器-->
    <mappers>
        <!--        mapper:需要指明xml文件的位置-->
        <mapper resource="com/hqyj/lxh/mapper/UserMapper.xml"/>
        <mapper resource="com/hqyj/lxh/mapper/EmployeeMapper.xml"/>
    </mappers>

    
</configuration>

获取Factory

//定义一个SqlSession对象
private SqlSession sqlSession;
//定义一个InputStream对象
private InputStream inputStream;
//定义一个UserMapper对象
private EmployeeMapper employeeMapper;
//Junit在运行@Test之前执行的方法
@Before
public void before() throws IOException {
    //1.创建一个字符串 值为sql语句映射文件xml文件的路径
    String resourcePath="config/mybatis-config.xml";
    //2.读取映射文件
    inputStream = Resources.getResourceAsStream(resourcePath);
    //3.通过 SqlSessionFactory 创建 sqlSessionFactory 对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //4.创建sqlsession对象 用于操作数据库对象
    sqlSession = sqlSessionFactory.openSession();
    //5.找到UserMapper接口对象
    employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
}

//在Junit中 在运行@Test之后执行的方法
@After
public void after() throws IOException {
    sqlSession.close();
    inputStream.close();
}
#{}和${}

#{}方式传值是安全的,起占位符作用,为参数占位符 ?,即sql 预编译,能防止sql 注入

${}为字符串替换,即 sql 拼接,不能防止sql 注入

核心对象

MyBatis 的三个基本要素是:

  1. 映射文件(Mapper XML):映射文件定义了 SQL 语句与 Java 接口方法之间的映射关系。它包含用于执行数据库操作的 SQL 语句,还定义了输入参数和输出结果的映射规则。映射文件通常与持久化的实体类(POJO)相关联。

  2. Java 接口:Java 接口定义了要执行的数据库操作,例如查询、插入、更新和删除等。接口中的方法名称和参数类型要与映射文件中定义的 SQL 语句一致。MyBatis 根据接口方法的调用动态生成与 SQL 语句对应的实现。

  3. 配置文件(Configuration XML):配置文件是 MyBatis 的核心配置文件,它包含了所有的设置项和属性配置。配置文件定义了数据源、数据库连接池、事务管理器以及映射文件的路径等重要配置信息。它也可以包含一些全局设置和插件配置。

通过这三个基本要素,MyBatis 实现了 SQL 与 Java 代码的分离,简化了数据库操作的实现。开发人员只需要通过接口方法调用,而无需显式编写 SQL 语句,从而提高了开发效率和可维护性。

MyBatis 的核心接口和类,如下所示

                           bulid()                        openSession()
SqlSessionFactoryBuilder  --------->  sqlSessionFactory  --------------->  sqlSession 
  • 每个 MyBatis 应用程序都以一个 SqlSessionFactory 对象的实例为核心;

  • 首先获取 SqlSessionFactoryBuilder 对象,可以根据 XML 配置文件或者 Configuration 类的实例构建该对象;

  • 然后获取 SqlSessionFactory 对象,该对象实例可以通过 SqlSessionFactoryBuilder 对象来获取;

  • 有了 SqlSessionFactory 对象之后,就可以进而获取 SqlSession 实例。SqlSession 对象中完全包含以数据库为背景的所有执行 SQL 操作的方法,用该实例可以直接执行已映射的 SQL 语句;

  • 每个线程都有自己的 SqlSession 实例,SqlSession 实例不能被共享,也不是线程安全的。因此 SqlSession 的作用域范围是 request 作用域或方法体作用域内。

1、SqlSessionFactoryBuilder
  • SqlSessionFactoryBuilder 会根据配置信息或者代码生成 SqlSessionFactory;

  • 由于字节流和字符流都属于读取配置文件的方式,所以就很容易想到构建一个 SqlSessionFactory 有两种方式,即:读取 XML 配置文件和编写代码。一般习惯为采取 XML 配置文件的方式来构造 SqlSessionFactory,这样一方面可以避免硬编码,另一方面方便日后配置人员修改,避免重复编译代码;

  • SqlSessionFactoryBuilder 的最大特点就是用过即丢。创建 SqlSessionFactory 对象后,这个类就不存在,因SqlSessionFactoryBuilder 的最佳范围就是存在于方法体内,也就是局部变量。

2、SqlSessionFactory
  • SqlSessionFactory 是工厂接口而不是现实类,他的任务就是创建 SqlSession;
  • 所有的 MyBatis 应用都以 SqlSessionFactory 实例为中心,SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 对象来获取;
  • SqlSessionFactory 对象一旦创建,就会在整个应用程序过程中始终存在。没有理由去销毁或再创建它,并且在应用程序运行中也不建议多次创建 SqlSessionFactory。因此 SqlSessionFactory 的最佳作用域是 Application,即随着应用程序的生命周期一直存在。这种“存在于整个应用运行期间,并且只存在一个对象实例”的模式就是所谓的单例模式(指在运行期间有且仅有一个实例)。
3、SqlSession

SqlSession 是用于执行持久化操作的对象,类似于 JDBC 中的 Connection。它提供了面向数据库执行 SQL 命令所需的所有方法,可以通过 SqlSession 实例直接运行已映射的 SQL 语句。

SqlSession 的用途主要有两种:

  • 获取映射器。让映射器通过命名空间和方法名称找到对应的 SQL,并发送给数据库,执行后返回结果;
  • 直接通过“命名空间(namespace)+SQL id”的方式执行 SQL,不需要获取映射器。
  • SqlSession 对应一次数据库会话。由于数据库会话不是永久的,因此 SqlSession 的生命周期也不是永久的,每次访问数据库时都需要创建 SqlSession 对象。

映射器

映射器(Mapper)是 MyBatis 中用于定义与数据库交互的接口。映射器接口定义了要执行的数据库操作,例如查询、插入、更新和删除等。接口中的方法名称和参数类型要与映射文件中定义的 SQL 语句一致。

在 MyBatis 中,映射器接口是通过 Java 接口来定义的,而实际的 SQL 语句通过映射文件(Mapper XML)来映射和配置。

以下是一个使用映射器的示例:

public interface EmployeeMapper {
    Employee getEmployeeById(int id);
    void insertEmployee(Employee employee);
    void updateEmployee(Employee employee);
    void deleteEmployee(int id);
}

在上述示例中,EmployeeMapper 是一个映射器接口,定义了 getEmployeeByIdinsertEmployeeupdateEmployeedeleteEmployee 等数据库操作方法。

在映射文件中,需要与EmployeeMapper接口中的方法名称和参数类型一致,并配置对应的 SQL 语句。例如:

<select id="getEmployeeById" resultType="Employee" parameterType="int">
    SELECT * FROM employee WHERE id = #{id}
</select>

<insert id="insertEmployee" parameterType="Employee">
    INSERT INTO employee (id, name, email) VALUES (#{id}, #{name}, #{email})
</insert>

<update id="updateEmployee" parameterType="Employee">
    UPDATE employee SET name = #{name}, email = #{email} WHERE id = #{id}
</update>

<delete id="deleteEmployee" parameterType="int">
    DELETE FROM employee WHERE id = #{id}
</delete>

在业务逻辑代码中,可以像调用普通的 Java 接口一样调用映射器接口的方法来执行数据库操作。

EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

Employee employee = employeeMapper.getEmployeeById(1);
employeeMapper.insertEmployee(new Employee(2, "John Doe", "john@example.com"));
employeeMapper.updateEmployee(new Employee(1, "Jane Smith", "jane@example.com"));
employeeMapper.deleteEmployee(2);

这样就可以通过映射器接口来执行相应的数据库操作了。

MyBatis 映射器的主要元素

MyBatis 映射器(Mapper)中的主要元素包括以下几个:

  1. select:用于执行查询操作的元素。可以使用 SQL 语句进行查询,并将查询结果映射到 Java 对象或集合。

  2. insert:用于执行插入操作的元素。可以将数据插入到数据库中。

  3. update:用于执行更新操作的元素。可以更新数据库中的数据。

  4. delete:用于执行删除操作的元素。可以从数据库中删除数据。

这些元素可以通过映射文件(Mapper XML)中的对应标签进行配置。下面是一个示例,展示了映射文件中的这些元素的使用:

<mapper namespace="com.example.EmployeeMapper">
    <select id="getEmployeeById" resultType="com.example.Employee" parameterType="int">
        SELECT * FROM employee WHERE id = #{id}
    </select>

    <insert id="insertEmployee" parameterType="com.example.Employee">
        INSERT INTO employee (id, name, email) VALUES (#{id}, #{name}, #{email})
    </insert>

    <update id="updateEmployee" parameterType="com.example.Employee">
        UPDATE employee SET name = #{name}, email = #{email} WHERE id = #{id}
    </update>

    <delete id="deleteEmployee" parameterType="int">
        DELETE FROM employee WHERE id = #{id}
    </delete>
</mapper>

在上述示例中,namespace 属性指定了映射器接口的全限定名。各个元素的id属性定义了映射器接口中对应的方法名称。

  • select 元素中的 resultType 属性指定了查询结果的目标类型。parameterType 属性指定了传递给 SQL 语句的参数类型。

  • insertupdatedelete 元素的 parameterType 属性指定了要操作的数据的类型。

这些元素还可以包含其他属性和子元素,用于更详细地配置映射关系、参数映射、结果映射等。例如,select 元素可以使用 resultMap 子元素来指定更复杂的结果映射规则。

除了上述的元素之外,还有其他的元素可以用于配置映射器,例如 sql 元素可以用来定义可重用的 SQL 片段。另外,还可以使用动态 SQL 元素来根据条件动态生成 SQL 语句。

这些元素的配置和使用可以根据具体的业务需求进行灵活调整。希望这个解答对您有所帮助!如果您还有其他问题,请随时提问。

实例

首先,我们可以使用以下的 SQL 语句来创建员工表:

CREATE TABLE employee (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT NOT NULL,
    email VARCHAR(100),
    department VARCHAR(50) NOT NULL
);

然后,在 Employee 类中定义属性,并为它们生成 settergetter 方法:

public class Employee {
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    private String department;

    // 省略 setter 和 getter 方法
}

接下来,在 EmployeeMapper.xml 文件中,我们定义一些 SQL 映射语句:

<!-- 根据 id 查询员工 -->
<select id="getEmployeeById" resultType="Employee">
    SELECT * FROM employee WHERE id = #{id};
</select>

<!-- 查询所有员工 -->
<select id="getAllEmployees" resultType="Employee">
    SELECT * FROM employee;
</select>

<!-- 根据关键字模糊查询员工 -->
<select id="getEmployeesByKeyword" resultType="Employee">
    SELECT * FROM employee WHERE name LIKE '%' #{keyword} '%';
</select>

EmployeeMapper 接口中定义上述 SQL 映射语句对应的方法:

public interface EmployeeMapper {
    Employee getEmployeeById(Integer id);
    List<Employee> getAllEmployees();
    List<Employee> getEmployeesByKeyword(String keyword);
}

最后,我们就可以在业务逻辑代码中使用 MyBatis 查询员工了:

// 基于 mybatis-config.xml 构建 SqlSessionFactory 对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

// 创建 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();

// Mapper 接口方式查询员工
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.getEmployeeById(1);
System.out.println(employee);

List<Employee> employees = employeeMapper.getAllEmployees();
System.out.println(employees);

List<Employee> employees1 = employeeMapper.getEmployeesByKeyword("张");
System.out.println(employees1);

// 关闭 SqlSession 对象
sqlSession.close();

Shiro

映射语句:

<!-- 根据 id 查询员工 -->
<select id="getEmployeeById" resultType="Employee">
    SELECT * FROM employee WHERE id = #{id};
</select>

<!-- 查询所有员工 -->
<select id="getAllEmployees" resultType="Employee">
    SELECT * FROM employee;
</select>

<!-- 根据关键字模糊查询员工 -->
<select id="getEmployeesByKeyword" resultType="Employee">
    SELECT * FROM employee WHERE name LIKE '%' #{keyword} '%';
</select>

EmployeeMapper 接口中定义上述 SQL 映射语句对应的方法:

public interface EmployeeMapper {
    Employee getEmployeeById(Integer id);
    List<Employee> getAllEmployees();
    List<Employee> getEmployeesByKeyword(String keyword);
}

最后,我们就可以在业务逻辑代码中使用 MyBatis 查询员工了:

// 基于 mybatis-config.xml 构建 SqlSessionFactory 对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

// 创建 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();

// Mapper 接口方式查询员工
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.getEmployeeById(1);
System.out.println(employee);

List<Employee> employees = employeeMapper.getAllEmployees();
System.out.println(employees);

List<Employee> employees1 = employeeMapper.getEmployeesByKeyword("张");
System.out.println(employees1);

// 关闭 SqlSession 对象
sqlSession.close();

Shiro

没写完

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值