ssm入门

为避免白学告警这种情况的发生,只上重点,只上干货

文章目录

  • 1.介绍ssm
  • 2.Spring篇
    • 基础内容
      • 什么是IOC(控制反转)
      • Spring和IOC之间的关系
      • IOC容器的作用以及内部存放
      • IoC入门案例
      • DI(Dependency Injection)依赖注入
      • 依赖注入的概念
      • IOC容器中哪些bean之间要建立依赖关系
      • DI入门案例
    • IOC相关内容
      • bean基础配置
      • bean的实例化
      • bean的生命周期
      • 依赖注入


1.介绍ssm

首先介绍一下SSM框架,以避免认识不清晰的情况发生

ssm中讲的是spring framework

介绍一下架构

ssm入门_第1张图片
(1)核心层
Core Container:核心容器,这个模块是Spring最核心的模块,其他的都需要依赖该模块

(2)AOP层
AOP:面向切面编程,它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强

Aspects:AOP是思想,Aspects是对AOP思想的具体实现

(3)数据层
Data Access:数据访问,Spring全家桶中有对数据访问的具体实现技术

Data Integration:数据集成,Spring支持整合其他的数据层解决方案,比如Mybatis

Transactions:事务,Spring中事务管理是Spring AOP的一个具体实现

(4)Web层

(5)Test层
Spring主要整合了Junit来完成单元测试和集成测试

对Spring的学习主要包含四部分内容:

ssm入门_第2张图片

ssm入门_第3张图片

为解决耦合度较高的问题,Spring提出了一个解决方案:

使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象

这也就是Spring的核心思想


2.Spring篇

首先,这几个概念要是很清楚就直接往下拉看案例

ssm入门_第4张图片


基础内容

什么是IOC(控制反转)

控制反转,使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转,简单点说,就是创建对象的控制权,被反转到了Spring框架上

控制反转英文全称:Inversion of Control。控制反转通过依赖注入(DI)方式实现对象之间的松耦合关系。程序运行时,依赖对象由辅助程序动态生成并注入到被依赖对象中,动态绑定两者的使用关系。Spring IoC 容器就是这样的辅助程序,它负责对象的生成和依赖的注入,然后再交由我们使用。

IoC容器:具有依赖注入功能的容器,可以创建对象的容器。IoC容器负责实例化、定位、配置应用程序中的对象并建立这些对象之间的依赖。

Spring和IOC之间的关系

  • Spring技术对IOC思想进行了实现
  • Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的"外部"
  • IOC思想中的 别人[外部] 指的就是Spring的IOC容器

它可以装载bean,也是一种降低对象之间耦合关系的设计思想。(比如租房子。以前租房子需要一个房子一个房子找,费时费力,然后现在加入一个房屋中介,把你需要的房型告诉中介,就可以直接选到需要的房子,中介就相当于spring容器。)

IOC容器的作用以及内部存放

  • IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
  • 被创建或被管理的对象在IOC容器中统称为Bean
  • IOC容器中放的就是一个个的Bean对象
  • Bean是被实例的、组装的、及被Spring容器管理的Java对象。
  • Spring容器会自动完成Bean对象的实例化。
  • 创建应用对象之间的协作关系的行为被称为:装配,这就是依赖注入的本质。

补充一下Dao层和Service层的概念:
Service是业务层,Dao是数据访问层,这样的分层是基于MVC架构来说的。

Dao层:全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表、某个实体的增删改查

Service层:被称为服务,肯定是相比之下比较高层次的一层结构,相当于将几种操作封装起来。

具体起来,Dao的作用是封装对数据库的访问:增删改查,不涉及业务逻辑,只是达到按某个条件获得指定数据的要求;
而Service,则是专注业务逻辑,对于其中需要的数据库操作,都通过Dao去实现。

简单来说就是Dao层是底层,具体到某一张表的增删查改,可以理解为有多少张表就有多少个Dao层,而Service成可以理解为是Dao层的
“上司”,通过Service层来控制Dao层。

一个Service层控制一个或者多个Dao层。


IoC入门案例

入门案例的思路:

ssm入门_第5张图片
ssm入门_第6张图片

步骤1:

导入Spring坐标

<!--  定义项目的依赖  -->
    <dependency>
      <groupId>org.springframework</groupId>
      <!--  配置依赖的groupId,表示所依赖的模块或组件的唯一ID  -->
      <artifactId>spring-context</artifactId>
      <!--  配置依赖的artifactId,表示所依赖的模块或组件的名称  -->
      <version>5.2.10.RELEASE</version>
      <!--  配置依赖的版本号  -->
    </dependency>

博主用的是:IntelliJ IDEA 2022.2.3 (Ultimate Edition),是会有警告的,这里不用管,因为5.2.10.RELEASE是最稳定的目前
ssm入门_第7张图片

步骤2:

定义Spring管理的类(接口)

public interface BookDao {
    public void save();
}
public interface BookService {
    public void save();
}

public class BookServiceImpl implements BookService {
    //5.删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
    //6.提供对应的set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

步骤3:

创建Spring配置文件,配置对应类作为Spring管理的bean

ssm入门_第8张图片

bean定义时id属性在同一个上下文中不能重复

步骤4:

初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean

public class App {
    public static void main(String[] args) {
        BookService bookService = new BookServiceImpl();
        bookService.save();
    }
}

DI(Dependency Injection)依赖注入

依赖注入的概念

在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入

业务层要用数据层的类对象,以前是自己 new 的,现在自己不new了,靠 别人[外部其实指的就是IOC容器] 来给注入进来,这种思想就是依赖注入

IOC容器中哪些bean之间要建立依赖关系

这个需要程序员根据业务需求提前建立好关系,如业务层需要依赖数据层,service就要和dao建立依赖关系

介绍完Spring的IOC和DI的概念后,我们会发现这两个概念的最终目标就是:充分解耦

具体实现靠:

  • 使用IOC容器管理bean(IOC)
  • 在IOC容器内将有依赖关系的bean进行关系绑定(DI)
  • 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系.

DI入门案例

案例思想:

ssm入门_第9张图片

具体实现:

ssm入门_第10张图片

步骤1:

删除使用new的形式创建对象的代码

public class BookServiceImpl implements BookService {
    //5.删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;

    public void save() {

        bookDao.save();
    }
}

步骤2:

提供依赖对象对应的setter方法

public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

步骤3:

配置service与dao之间的关系

ssm入门_第11张图片

ref对应的是bean的名称
name对应的是属性的名称

IOC相关内容

下面详细讲解这三个内容

  1. bean如何定义配置
  2. DI如何定义配置
  3. 容器对象如何获取

bean基础配置

bean的语法:

<bean id="" class="">

这张表包括bean标签的功能,使用方式,id和class属性的作用

ssm入门_第12张图片

这里就简单带过

在spring的配置文件中,给name配置多个值

    <!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
    <bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>

bean的作用范围:

bean的作用范围由scope属性决定

scope取singleton时bean为单例,scope取prototype时bean为非单例

之所以bean默认为单例,是因为在Spring的IOC容器中只会有该类的一个对象
bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高

适合交给容器进行管理的bean的scope设置为singleton
不适合交给容器进行管理的bean的scope设置为prototype

ssm入门_第13张图片

bean的实例化

实例化bean有三种方法

首先是无参的构造方法实例化对象,比较常用

//提供可访问的构造方法
public class BookDaoImpl implements BookDao{
	public void save(){
		System.out.println("...")
	}
}
配置
<bean
	id="bookDao"
	class="..."
	/>

补充一下什么是工厂
工厂模式是属于创建型模式的,通过工厂获取一个一个的新对象。说白了,工厂就是用来 new(创建)对象的,因此把它化分到创建型这一类中。
这里就说一下简单工厂
简单地说,简单工厂模式通常就是这样,一个工厂类 XxxFactory,里面有一个静态方法,根据我们不同的参数,返回不同的派生自同一个父类(或实现同一接口)的实例对象。
我们强调职责单一原则,一个类只提供一种功能,例如FoodFactory 的功能就是只要负责生产各种 Food。

ssm入门_第14张图片

第二个方法:使用静态工厂实例化bean

这里了解即可

建议先构建一个这样的结构

ssm入门_第15张图片

在spring配置文件中

<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
package com.itheima.factory;

import com.itheima.dao.OrderDao;
import com.itheima.dao.impl.OrderDaoImpl;
//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("factory setup....");
        return new OrderDaoImpl();
    }
}

方法三:实例化工厂(了解)

方法2,3都是针对早期遗留问题

    <!--方式三:使用实例工厂实例化bean-->
    <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>

    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>

方法四:使用FactoryBean实例化(重点)

1.创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法

public  class  UserDaoFactoryBean  implements  FactoryBean<UserDao>  {
    //实现FactoryBean接口,此处代表工厂生产产品的类型为UserDao

    //代替原始实例工厂中创建对象的方法
    public  UserDao  getObject()  throws  Exception  {
        //通过定义的工厂方法获取产品实例
        return  new  UserDaoImpl();
        //实例化一个实现了UserDao接口的实现类对象
    }

    public  Class<?>  getObjectType()  {
        //获取工厂生产的产品类型
        return  UserDao.class;
        //返回工厂创建的产品类型
    }
}

2.在Spring的配置文件中进行配置

<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/> 

3.AppForInstanceUser运行类不用做任何修改,直接运行

public class AppForInstanceUser {
    public static void main(String[] args) {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

//验证单例
        UserDao userDao1 = (UserDao) ctx.getBean("userDao");
        UserDao userDao2 = (UserDao) ctx.getBean("userDao");
        System.out.println(userDao1);
        System.out.println(userDao2);
//        userDao.save();

    }
}

这里可能出现这种报错:java: 错误: 不支持发行版本 5
这里在pom.xml文件下的project标签下复制以下代码

<build>
      <plugins>
           <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

source和target按照你自己的版本来

正确的编译结果如下:
ssm入门_第16张图片

这种方式在Spring去整合其他框架的时候会被用到

查看源码会发现,FactoryBean接口其实会有三个方法,分别是:

  • getObject(),被重写后,在方法中进行对象的创建并返回
  • getObjectType(),被重写后,主要返回的是被创建类的Class对象
  • 没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true

总结: 目前只会用到构造方法,要重点掌握

bean的生命周期

  • 生命周期: 从创建到消亡的完整过程
  • bean生命周期 : bean从创建到销毁的整体过程
  • bean生命周期控制:在bean创建后到销毁前做一些事情

对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:

ssm入门_第17张图片

Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置 init-method 和 destroy-method

在BookServiceImpl完成这两个接口的使用:

修改BookServiceImpl类,添加两个接口 InitializingBean , DisposableBean 并实现接口中的两个方法 afterPropertiesSet 和 destroy

// 定义一个BookServiceImpl类,实现BookService接口,并且同时实现了InitializingBean和DisposableBean接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao; // 声明一个私有的BookDao类型的实例变量

    // 定义一个set方法,用于依赖注入书籍数据访问对象
    public void setBookDao(BookDao bookDao) {
        System.out.println("set .....");
        this.bookDao = bookDao;
    }

    // 定义一个保存方法,用于保存书籍信息
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }

    // 实现DisposableBean接口的方法之一,当bean销毁时调用
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }

    // 实现InitializingBean接口的方法之一,当bean初始化完成后调用
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
}

需注意细节:

  • InitializingBean接口中的afterPropertiesSet方法,翻译过来为 属性设置之后
  • 对于BookServiceImpl来说,bookDao是它的一个属性
  • setBookDao方法是Spring的IOC容器为其注入属性的方法

关闭容器

暴力方法:close方法

ApplicationContext中没有close方法
需要将ApplicationContext更换成ClassPathXmlApplicationContext

ClassPathXmlApplicationContext ctx = new
  ClassPathXmlApplicationContext("applicationContext.xml");

调用ctx的close()方法

 //关闭容器
 ctx.close();

注册钩子关闭容器

在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器
调用ctx的registerShutdownHook()方法

ctx.registerShutdownHook();

不同点:
close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。

补充:什么是jvm?
(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。
(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。
(3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。

依赖注入

DI (Dependency Injection):依赖注入是指在 Spring IOC 容器创建对象的过程中,将所依赖的对象通过配置进行注入。我们可以通过依赖注入的方式来降低对象间的耦合度。

ssm入门_第18张图片

setter注入:

1)创建学生类Student

package com.mkbk.spring.pojo;

public class Student implements Person{

    private Integer sid;

    private String sname;

    private Integer age;

    private String gender;

    public Student(Integer sid, String sname, Integer age, String gender) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
        this.gender = gender;
    }

    public Student() {
    }

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

2)配置bean时为属性赋值

<?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 id="studentOne" class="com.mkbk.spring.pojo.Student" scope="singleton"></bean>
    <bean id="studentTwo" class="com.mkbk.spring.pojo.Student" scope="singleton">
        <property name="sid" value="1001"></property>
        <property name="sname" value="1001"></property>
        <property name="age" value="23"></property>
        <property name="gender" value="男"></property>

    </bean>


</beans>

3)测试

public class IOCByXMLTest {

    public void testDI(){
        ApplicationContext ioc=new ClassPathXmlApplicationContext("Application.xml");
//        Student student=ioc.getBean("studentTwo",student.class);
    }

    public void testIOC(){
        ApplicationContext ioc=new ClassPathXmlApplicationContext("ApplicationContext.xml");

//        Student studentOne=(Student) ioc.getBean("studentOne");
//        Student student=ioc.getBean(Student.class);
        Student studentOne=ioc.getBean("studentOne",Student.class);
        System.out.println(studentOne);
    }
}

构造器注入

1)在Student类中添加有参构造

public Student(Integer id, String name, Integer age, String sex) {
  this.id = id;
  this.name = name;
  this.age = age;
  this.sex = sex;
}

2)配置bean

<bean id="studentTwo" class="com.atguigu.spring.bean.Student">
  <constructor-arg value="1002"></constructor-arg>
  <constructor-arg value="李四"></constructor-arg>
  <constructor-arg value="33"></constructor-arg>
  <constructor-arg value="女"></constructor-arg>
</bean>

3)测试

@Test
public void testDIBySet(){
  ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");
  Student studentOne = ac.getBean("studentTwo", Student.class);
  System.out.println(studentOne);
}

分割线-----------------------------------------------------------------更新中…

你可能感兴趣的:(ssm,junit,spring,java)