SSM框架介绍、浅谈Spring基础知识

SSM

Spring+SpringMVC+MyBatis

smm框架是Java开发中最常用的框架

SSM框架说明

  • Spring

    Spring Framework,是Spring家族的核心。

  • Spring MVC

    SpringMVCSpring Framework 的核心子项目,提供了一系列功能,使得开发者能够快速开发灵活、易于维护的Web应用程序。

  • MyBatis

    MyBatis 是基于 Java 的持久层框架,用于和数据库映射;

    MyBatis 避免了几乎所有的JDBC代码和手动设置参数以及获取结果集的工作;

    MyBatis 通过注解方式或者xml配置文件的方式来配置SQL和映射关系,灵活性非常高。

spring

Spring

Spring定义

​ Spring是一款主流的 Java EE 开源框架,目的是用于简化Java企业级引用的开发难度和开发周期。从简单性、可测试性的角度而言,任何Java应用都可以从Spring中受益。Spring框架提供自己提供功能外,还提供整合其他技术和框架的能力。

​ 自2004年4月,Spring1.0 版正式发布以来,Spring已经步入到了第6个大版本,即 Spring6,本课程采用 Spring5.3.24 正式版本。

Spring官网地址:https://spring.io/

image-20230715063053243

Spring核心

Spring指的是Spring Framework,通常我们称之为Spring框架。

Spring是一个资源整合的框架,可以整合一切可以整合的资源[自身+第三方框架]

Spring是一个生态,包含很多子模块,其中Spring Framework是生态的核心

framework

Spring的两个核心模块

  • IoC控制反转

    Inverse of Control 的简写,为 控制反转,指把创建对象交给 Spring 进行管理。

    即:反转资源获取方向,把自己创建资源、向环境索取资源的方式变为环境自动将资源准备好,我们享受资源注入。

  • AOP面向切面编程

    Aspect Oriented Programming 的简写,为 面向切面编程。AOP 用来封装多个类的公共行为,将那些与业务无关,却为业务模块共同调用的逻辑封装起来,减少系统的重复代码。

Spring版本

常用的spring版本

  • spring6:只支持JDK17以上版本
  • spring5:支持JDK8版本

Spring Framework使用流程

  1. 添加依赖,刷新Maven

    <!-- 引入spring context依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.24</version>
    </dependency>
    
  2. 创建类,添加@Component注解

    @Component
    public class User {
        public void say(){
            System.out.println("user say...");
        }
    }
    
  3. 通过Spring获取类对象

    • 创建IOC容器:springframework会将创建好的对象放入IOC容器中

      //指定以注解方式创建对象
      ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.peng.spring.example");
      //指定以xml方式创建对象
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
      //指定以xml方式创建对象
      ApplicationContext applicationContext = new FileSystemXmlApplicationContext("file:D:/applicationContext.xml");
      
    • 获取对象:从IOC容器中获取已经创建好的对象

    • 调用对象方法

    /*
        - 创建IOC容器:springframework会将创建好的对象放入IOC容器中
        - 获取对象:从IOC容器中获取已经创建好的对象
        - 调用对象方法
    */
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.peng.spring.example");
    User user = (User) applicationContext.getBean(User.class);
    user.say();
    

相关概念

IoC

IoC(Inversion of Control,控制反转)是一种编程思想;

IoC 是将对象的创建和管理交由框架来完成,而不是由开发人员手动创建和管理。

IoC 是一种控制反转的思想,而依赖注入 DI和IoC容器是对 IoC 的具体实现。

IoC容器

IoC容器是用来实现IoC思想的一个工具或者说技术手段,是真实存在的

它能够自动扫描应用程序中的对象,将它们实例化,并自动注入它们所需要的依赖对象,使应用程序的开发人员能够更加专注于业务逻辑的实现,而不用关心对象的创建和管理。Spring通过IoC容器来管理所有的Java对象的实例化和初始化,控制着对象与对象之间的依赖关系。

我们将由IoC容器管理的Java对象成为 Spring Bean,它与使用关键字 new 创建的Java对象没有任何区别。

依赖注入DI

DI (Dependency Injection):依赖注入,依赖注入实现了控制反转的思想,是指Spring创建对象的过程中,将对象依赖属性通过配置进行注入。

所以 IoC 是一种控制反转的思想,而依赖注入 DI 是对 IoC 的一种具体实现。

Bean管理:指Bean对象的创建,以及Bean对象中属性的赋值

IoC容器实现

Spring中的IoC容器就是IoC思想的一个落地产品实现。IoC容器中管理的组件也叫做bean。在创建bean之前,首先需要创建IoC容器,Spring提供了IoC容器的两种实现方式

  • BeanFactory

    这是IoC容器的基本实现,是Spring内部使用的接口,面向Spring本身,不提供给开发人员使用。

  • ApplicationContext

    BeanFactory的子接口,提供了更多高级特性,面向Spring的使用者,几乎所有场合都使用 ApplicationContext,而不使用底层的BeanFactory。

源码说明:

image-20230429223910264

  • ApplicationContext的主要实现类

    类型说明
    AnnotationConfigApplicationContext使用注解方式构建IoC容器
    ClassPathXmlApplicationContext使用XML配置文件方式构建Spring IoC容器

依赖注入DI

DI (Dependency Injection):依赖注入,依赖注入实现了控制反转的思想;

是指Spring创建对象的过程中,将对象依赖属性通过配置进行注入。

所以 IoC 是一种控制反转的思想,而依赖注入 DI 是对 IoC 的一种具体实现。

注解管理Bean

Bean对象定义及获取

在Spring框架规范中,所有由spring管理的对象都称之为Bean对象。

Bean对象定义

Spring提供了以下多个注解,这些注解可以直接标注在java类上,将它们定义成Spring Bean。

注解说明
@Component该注解用于描述Spring中的Bean,它是一个泛化的概念,仅仅标识容器中的一个组件(Bean),并且可以作用在任何层次,例如Service层、Dao层等,使用时只需将该注解标注在相应的类上即可。
@Repository该注解用于数据访问层(Dao层)的类标识为Spring中的Bean,功能与@Component相同。
@Service该注解通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同。
@Controller该注解通常作用在控制层(如SpringMVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。
Bean对象获取

​ 通过 ApplicationContext 对象获取:调用 ApplicationContext 对象的 getBean() 方法,传入对应类的类型即可获取该 Bean 对象,示例:

ApplicationContext context = new AnnotationConfigApplicationContext("包扫描路径");
User user = context.getBean(类名.class);

依赖注入DI

@Value注解

@Value 注入是将属性值直接注入到 bean 中,主要用于注入一些简单类型的属性(如字符串、基本类型等);

使用时需要注意属性的类型和格式,否则会导致注入失败。

//@Value中必须加引号
@Value("root")
private String username;
@Value("root")
private String password;
@Value("jdbc:mysql://localhost:3306/tedu")
private String url;
@Autowired注解

自动装配注解,注入对象类型和接口类型的数据

@Autowired 注入是将对象注入到 bean 中,并且在注入对象时会根据依赖注入容器中 bean的类型 进行匹配。

  • 默认使用byType进行装配,想要通过byName方式进行装配则需要搭配@Qualifier注解进行使用

  • 如果容器中有多个类型匹配的bean存在,则会抛出异常。

  • @Autowired注入常用于注入复杂对象、接口类型的属性或其他bean实例。

  • @Autowired注解可添加的位置

    1. 属性上
    2. setter方法上
    3. 构造方法上
  • 注入有多个实现类的接口时,不可直接注入,否则会报NoUniqueBeanDefinitionException异常

@Qualifier注解

使用@Autowired注入有多个实现类的接口时,不可直接注入,容器无法识别应该选择哪个实现类注入

  • @Qualifier注解是用于限定一个接口有多个实现类时,根据指定的限定条件来选择具体的实现类的注解;

  • 当Spring容器中存在多个实现同一接口的bean时,在注入时,由于不能确定注入哪一个实现类,就需要通过@Qualifier注解来明确指定要注入的bean的名称。

  • @Qualifier与@Autowired联合使用,可以指定需要注入的实现类

  • 格式:

    • 直接使用类名,value中的参数必须将类名首字母小写
    @Autowired
    @Qualifier(value = "cacheImpl1")
    private Cache cache;
    
    • 在实现类中添加注解时,给类添加组件名

      • 第1步:在 UserCache 中添加 @Autowired注解@Qualifier注解

        @Component
        public class UserCache {
            @Autowired
            @Qualifier("aaa")
            private Cache cache;
        }
        
      • 第2步:在 CacheImpl1 实现类中 @Component注解 中添加组件名

        @Component("aaa")
        public class CacheImpl1 implements Cache{
        }
        
    • 总结:在@Component注解中可以不用指定组件名称,默认为当前类的 类名首字母小写。

@Resource注解

@Resource 注解是 JavaEE 提供的注解之一,也支持在 Spring Framework 中使用。在 Spring 中,它可以用来注入 Bean 实例,与@Autowired注解的作用类似,但其也有自己的一些特点。

@Resource和@Autowired的区别

  • @Resource 注解是 JDK扩展包 中的,也就是说属于JDK的一部分,所以该解释是标准注解;而 @Autowired 注解是 Spring Framework 框架自己的。

  • 装配规则

    • @Resource 注解默认根据名称装配 byName

      @Resource(name = "resMapper1")
      private ResMapper resMapper;
      
    • 当未指定 name 时,则使用属性名作为 name 进行装配;

      使用resMapper属性名进行装配

      @Resource
      //等效于@Resource(name = "resMapper")
      private ResMapper resMapper;
      
    • 如果通过 name 也未找到,则会自动启动通过类型 byType 装配。

      上例中会按照ResMapper接口进行按类型匹配,若该接口只有一个实现类,则装配成功,若有多个实现类则会报NoUniqueBeanDefinitionException异常

    而@Autowired注解默认根据类型装配byType,如果想根据名称匹配,需要配合@Qualifier注解一起使用。

Bean作用域

说明

​ 在Spring框架中,Bean是按照作用域来创建的,常见的作用域有两种:SingletonPrototype。其中,Singleton (单例)是指整个应用中只有一个实例,并在第一次请求时创建实例。而 Prototype (多例)是指每次请求都会创建一个新的实例并返回,每个实例之间是相互独立的。可以通过 @Scope 注解来指定,默认是单实例。

单实例与多实例
  • 单实例

    单实例(Singleton)是指某个类只能创建唯一的一个实例对象,并且该类提供一个全局的访问点(静态方法)来让外界获取这个实例,常常用在那些只需要一个实例来处理所有任务的场景下,例如数据库连接。

    创建IoC容器时就创建bean对象,new AnnotationConfigApplicationContext

  • 多实例

    多实例(Multiple Instance)则是指可以在同一个类的定义下,创建多个实例对象。每个对象都是相互独立的,有自己的状态和行为;常常用于需要同时处理多个任务的场景。

    在IoC容器获取对象时才会创建对象,context.getBean

在Spring中可以通过 @Scope 注解来指定bean的作用域范围,具体如下

取值含义
@Scope(“singleton”)(默认在IoC容器中,这个bean的对象为单实例
@Scope(“prototype”)这个bean在IoC容器中有多个实例
应用分析
  • 第1步:在 cn.tedu.spring 下创建子包 scope ,并创建类 DBConnect

    @Scope(value = "singleton")
    @Component
    public class DBConnect {
    }
    
  • 第2步:创建测试类进行测试

    public class TestDBConnect {
        @Test
        public void testScope(){
            ApplicationContext context = new AnnotationConfigApplicationContext("cn.tedu.spring.scope");
            // 第一次获取
            DBConnect dbConnect1 = context.getBean(DBConnect.class);
            System.out.println(dbConnect1);
            // 第二次获取
            DBConnect dbConnect2 = context.getBean(DBConnect.class);
            System.out.println(dbConnect2);
        }
    }
    
  • 总结

    • 当为单例模式 singleton 时,多次获取bean实例的地址是相同的

    • 当为多例模式 prototype 时,多次获取bean实例的地址是不同的

      image-20230525112036529

单例模式适用于需要共享数据并且需要避免重复创建实例的情况。而多例模式适用于需要动态地创建对象并提供独立实例的情况。

Spring作用域总结
  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
  • session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
  • global-session: 全局 session 作用域,仅仅在基于 Portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。

Bean生命周期

说明

程序中的每个对象都有生命周期,对象的创建、初始化、应用、销毁的整个过程称之为对象的生命周期;

在对象创建以后需要初始化,应用完成以后需要销毁时执行的一些方法,可以称之为是生命周期方法;

在spring中,可以通过 @PostConstruct@PreDestroy 注解实现 bean对象 生命周期的初始化和销毁时的方法。

  • @PostConstruct 注解

    生命周期初始化方法,在对象构建以后执行。

  • @PreDestroy 注解

    生命周期销毁方法,比如此对象存储到了spring容器,那这个对象在spring容器移除之前会先执行这个生命周期的销毁方法(注:prototype作用域对象不执行此方法)。

完整生命周期
  1. 实例化阶段 Instantiation(bean对象创建)

    在这个阶段中,IoC容器会创建一个Bean的实例,并为其分配空间。这个过程可以通过 构造方法 完成。

  2. 属性赋值阶段 Populate

    在实例化完Bean之后,容器会把Bean中的属性值注入到Bean中,这个过程可以通过 set方法 完成。

  3. 初始化阶段 Initialization(bean对象初始化)

    • 使用@PostConstruct注解对初始化操作进行标注
    • 在属性注入完成后,容器会对Bean进行一些初始化操作
  4. 使用阶段(可有可无)

    初始化完成后,Bean就可以被容器使用了

  5. 销毁阶段 Destruction

    • 销毁前可能会有一些销毁前操作需要进行,例如断开数据库等,通过@PreDestroy注解标注销毁预操作
    • 容器在关闭时会对所有的Bean进行销毁操作,释放资源。
    • 单例的 Bean 不会被销毁,原型模式的 Bean 会

image-20240417102922902

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if (instanceWrapper == null) {
    	// 实例化阶段
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    ...

    Object exposedObject = bean;

    try {
    	// 属性赋值阶段
        this.populateBean(beanName, mbd, instanceWrapper);
        // 初始化阶段
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        ...
    }

    ...
}

生命周期验证
//实体对象
@Component
public class Life {
    private String mean;
    public Life() {
        System.out.println("1.调用无参构造进行实例化");
    }
    @Value("Hello, World!")
    public void setMean(String mean) {
        System.out.println("2.调用 setMean 设置属性");
        this.mean = mean;
    }
    @PostConstruct
    public void init() {
        System.out.println("3.调用生命周期初始化 init 方法");
    }
    @PreDestroy
    public void destory() {
        System.out.println("5.关闭容器前,调用生命周期销毁方法 destory");
    }
}

//main方法调用
public class TestLife {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.peng.spring.life");
        Life life = context.getBean(Life.class);
        System.out.println("4.使用bean");
        context.close();
        System.out.println("关闭容器");
    }
}

结果:演示执行流程

image-20240417104832682

生命周期扩展

Bean初始化和销毁方法可以在Bean生命周期的特定时机执行自定义逻辑,方便地对Bean进行管理和配置。

  • 初始化常见应用场景
    • 创建数据库连接
    • 加载资源文件
    • 进行数据校验
  • 销毁常见应用场景
    • 断开数据库连接
    • 保存数据
    • 释放占用的资源
生命周期完整流程图

20210710134349143

引用外部属性文件

实际开发中,很多情况下我们需要对一些变量或属性进行动态配置,而这些配置可能不应该硬编码到我们的代码中,因为这样会降低代码的可读性和可维护性。

通过将应用程序特定的属性值放在属性文件中,我们还可以将应用程序的配置和代码逻辑进行分离,这可以使得我们的代码更加通用、灵活。

使用流程
  • 第1步:创建外部属性文件(在 resources 目录下创建文件,命名为:“xxx.properties”);

  • 第2步:引入外部属性文件(使用 @PropertySource("classpath:外部属性文件名") 注解);

  • 第3步:获取外部属性文件中的变量值 (使用 ${变量名} 方式);

  • 第4步:进行属性值注入

应用分析
  • resources 目录下创建文件 :database.properties

    spring.datasource.username=root
    spring.datasource.password=root
    spring.datasource.url=jdbc://mysql://localhost:3306/test
    
  • 工程目录下创建子包 file 并创建类 Database

    • 通过 @PropertySource 注解引入外部文件

    • 通过 ${变量名} 获取属性值

    • 通过 @Value() 注解进行属性值注入

    @Component
    @PropertySource("classpath:database.properties")
    public class Database {
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.user}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    
        @Override
        public String toString() {
            return "Database{" +
                    "url='" + url + '\'' +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }
    

自动扫描配置

自动扫描配置是 Spring 框架提供的一种基于注解(Annotation)的配置方式,用于自动发现和注册 Spring 容器中的组件。当我们使用自动扫描配置的时候,只需要在需要被 Spring 管理的组件(比如 Service、Controller、Repository 等)上添加对应的注解,Spring 就会自动地将这些组件注册到容器中,从而可以在其它组件中使用它们。

  • 在 Spring 中,通过 @ComponentScan 注解来实现自动扫描配置。

  • @ComponentScan 注解用于指定要扫描的包或类。

  • Spring 会在指定的包及其子包下扫描所有添加 @Component(或 @Service@Controller@Repository 等)注解的类,把这些类注册为 Spring Bean,并纳入 Spring 容器进行管理。

示例
  1. @Configuration:标识此类为配置类,添加该标识的类在项目启动时会优先加载
  2. @ComponentScan:在项目启动完成后会自动扫描指定包中的所有标识了@Component@Service@Controller@Repository 等注解的类,并将其作为bean加入IoC容器管理
  3. @Order:多个配置类时,该注解可以标识配置类加载顺序
@Configuration
@ComponentScan("com.peng.spring")
@Order(1)
public class SpringConfig {
}
  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值