栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring学习笔记

目录

1、Spring优点

2、Spring核心概念

2.1、IOC(Inversion of Control)控制反转

2.2、DI(Dependency Injection)依赖注入

2.3、核心概念小结

3、Bean基础配置

3.1、Bean实例化

3.2、Bean的生命周期

4、DI相关内容

5.1 setter注入

5.2、构造器注入

5.3、 自动配置

5.3.4 完成自动装配的配置

5.4 集合注入


1、Spring优点
  • Spring可以简化开发,降低企业级开发的复杂性,使开发变得更简单快捷

  • Spring可以框架整合,高效整合其他技术,提高企业级应用开发与运行效率

2、Spring核心概念

Spring核心概念主要包含IOC/DI、IOC容器和Bean

2.1、IOC(Inversion of Control)控制反转

(1)什么是控制反转?

  • 在使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转

(2)Spring和IOC之间的关系是什么呢?

  • Spring技术对IOC思想进行了实现

  • Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的“外部”

  • IOC思想中的外部指的就是Spring的IOC容器

(3)IOC容器的作用以及内部存放的是什么?

  • IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象

  • 被创建或被管理的对象在IOC容器中统称为Bean

  • IOC容器中放的就是一个个的Bean对象

2.2、DI(Dependency Injection)依赖注入

(1)什么是依赖注入呢?

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

    • 业务层要用数据层的类对象,以前是自己new的

    • 现在自己不new了,靠外部(指的IOC容器)注入进来

    • 这种思想称为依赖注入

(2)IOC容器中那些bean之间要建立依赖关系呢?

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

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

  • 使用IOC容器管理bean(IOC)

  • 在IOC容器内将有依赖关系的bean进行关系绑定(DI)

  • 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取的bean已经绑定了所有的依赖关系

2.3、核心概念小结

(1)什么是IOC/DI思想?

  • IOC:控制反转,控制反转的是对象的创建权

  • ID:依赖注入,绑定对象与对象之间的依赖关系

(2)什么是IOC容器?

Spring创建了一个容器用来存放所创建的对象,这个容器就叫IOC容器

(3)什么是Bean?

容器中所存放的一个个对象就叫Bean或Bean对象

3、Bean基础配置
 
 
 ​
 
 
 
 

3.1、Bean实例化

实例化Bean的三种方式,构造方法、静态工厂、实例工厂

(1)构造方法实例化


 
 //获取bean调用方法即可 
 ApplicationContext ctx = new 
             ClassPathXmlApplicationContext("applicationContext.xml");
         BookDao bookDao = (BookDao) ctx.getBean("bookDao");
         bookDao.save();
 ​
 //即使类对象的构造器是private也能创建对象 Spring底层使用的是反射
 //注意:构造方法在类中默认会提供,但是如果重写了构造方法,默认的就会消失,在使用的过程中需要注意,如果需要重写构造方法,最好把默认的构造方法也重写下。

(2)静态工厂实例化

 
 
 

(3)实例工厂实例化


 
 
 

实例工厂实例化的方式介绍完了,配置的过程还是比较复杂,所以Spring为了简化这种配置方式鸡提供了一种叫FactoryBean的方式来简化开发

3.1.1、FactoryBean的使用

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

public class UserDaoFactoryBean implements FactoryBean {
     //代替原始实例工厂中创建对象的方法
     public UserDao getObject() throws Exception {
         return new UserDaoImpl();
     }
     //返回所创建类的Class对象
     public Class getObjectType() {
         return UserDao.class;
     }
 }

(2)在Spring的配置文件中进行配置

 
FactoryBean接口其实会有三个方法,分别是:

 T getObject() throws Exception;
 ​
 Class getObjectType();
 ​
 default boolean isSingleton() {
         return true;
 }

方法一:getObject(),被重写后,在方法中进行对象的创建并返回

方法二:getObjectType():被重写后,主要返回的是被创建类的Class对象

方法三:没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认为true 需要改成非单例重写改成false即可 一般情况下我们都会采用单例,也就是采用默认即可 所以isSingleton()方法一般不需要进行重写

3.2、Bean的生命周期
  • bean创建之后,想要添加内容,比如用来初始化需要用到资源

  • bean销毁之前,想要添加内容,比如用来释放用到的资源

3.2.1、添加初始化和销毁方法
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
    //标示bean初始化对应的操作
    public void init() {
        System.out.println("init ...");
    }
    //表示bean销毁前对应的操作
    public void destroy() {
        System.out.ptintln("destory ...");
    }
}
3.2.2、配置生命周期
3.2.3、运行程序

发现init方法执行了,但是destroy方法却未执行,这是为什么呢?

  • Spring的IOC容器是运行在JVM中

  • 运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行

  • main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了

  • 所以没有调用对应的destroy方法

3.2.4、解决方案 3.2.4.1、close关闭容器
  • ApplicationContext中没有close方法

  • 需要将ApplicationContext更换成ClassPathXmlApplicationContext

ClassPathXmlApplicationContext ctx = new 
    ClassPathXmlApplicationContext("applicationContext.xml");
  • 调用ctx的close()方法

ctx.close();
3.2.4.2、注册钩子关闭容器
  • 在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器

  • 调用ctx的registerShutdownHook()方法

ctx.registerShutdownHook();

注意:registerShutdownHook在ApplicationContext中也没有

两种方式介绍完后,close和registerShutdownHook选哪个?

相同点:这两种都能用来关闭容器

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

分析上面的实现过程,会发现添加初始化和销毁方法,即需要编码也需要配置,实现起来步骤比较多也比较乱。

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

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

public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void save() {
        System.out.println("book service save ...");
        bookDao.save(); 
    }
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
}

4、DI相关内容
  • 向一个类中传递数据的方式有几种?

    • 普通方法(set方法)

    • 构造方法

  • 依赖注入描述了在容器中建立bean与bean之间的依赖关系的过程,如果bean运行需要的是数字或字符串呢?

    • 引用类型

    • 简单类型(基本数据类型与String)

Spring就是基于上面这些知识点,为我们提供了两种注入方式,分别是:

  • setter注入

    • 简单类型

    • 引用类型

  • 构造器注入

    • 简单类型

    • 引用类型

5.1 setter注入
  • 在bean中定义引用类型属性,并提供可访问的set方法

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
  • 配置中使用property标签ref属性注入引用类型对象




	
    
  • 配置中使用property标签value属性注入简单类型对象


        
     	
    

5.2、构造器注入
  • 注入引用类型数据

public class BookServiceImpl implements BookService{
    private BookDao bookDao;

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

 
          
 
  • 注入简单类型数据

public class BookDaoImpl implements BookDao {
    private String databaseName;
    private int connectionNum;

    public BookDaoImpl(String databaseName, int connectionNum) {
        this.databaseName = databaseName;
        this.connectionNum = connectionNum;
    }
}

        
        

说明:的配置顺序可以任意

  • 当构造函数中方法的参数名发生变化后,配置文件中的name属性也需要跟着变

  • 这两块存在紧耦合,具体该如何解决?

在解决这个问题之前,需要提前说明的是,这个参数名发生变化的情况并不多,所以上面的还是比较主流的配置方式,下面介绍的,大家都以了解为主。

方式一:删除name属性,添加type属性,按照类型注入


    
    
  • 这种方式可以解决构造函数形参名发生变化带来的耦合问题

  • 但是如果构造方法参数中有类型相同的参数,这种方式就不太好实现了

方式二:删除type属性,添加index属性,按照索引下标注入,下标从0开始


    
    
  • 这种方式可以解决参数类型重复问题

  • 但是如果构造方法参数顺序发生变化后,这种方式又带来了耦合问题

介绍完两种参数的注入方式,具体我们该如何选择呢?

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现

    • 强制依赖指对象在创建的过程中必须要注入指定的参数

  2. 可选依赖使用setter注入进行,灵活性强

    • 可选依赖指对象在创建过程中注入的参数可有可无

  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨

  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入

  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入

  6. 自己开发的模块推荐使用setter注入

这节中主要讲解的是Spring的依赖注入的实现方式:

  • setter注入

    • 简单数据类型


	
  • 引用数据类型

    
    	
    
  • 构造器注入

    • 简单数据类型


	

  • 引用数据类型
    
  • 依赖注入的方式选择上

    • 建议使用setter注入

    • 第三方技术根据情况选择

5.3、 自动配置 5.3.1 什么是依赖自动装配?
  • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

5.3.2 自动装配方式有哪些?
  • 按类型(常用)

  • 按名称

  • 按构造方法

  • 不启用自动装配

5.3.4 完成自动装配的配置

(1)将标签删除

(2)在标签中添加autowire属性

首先来实现按照类型注入的配置

    
    
    

注意事项:

  • 需要注入属性的类中对应属性的setter方法不能省略

  • 被注入的对象必须要被Spring的IOC容器管理

  • 按照类型在Spring的IOC容器中如果找到多个对象,会报NoUniqueBeanDefinitionException

一个类型在IOC中有多个对象,还想要注入成功,这个时候就需要按照名称注入,配置方式为:

 
    
 

注意事项:

  • 按照名称注入中的名称指的是什么?

    • bookDao是private修饰的,外部类无法直接方法

      • 外部类只能通过属性的set方法进行访问

      • 对外部类来说,setBookDao方法名,去掉set后首字母小写是其属性名

        • 为什么是去掉set首字母小写?

        • 这个规则是set方法生成的默认规则,set方法的生成是把属性名首字母大写前面加set形成的方法名

      • 所以按照名称注入,其实是和对应的set方法有关,但是如果按照标准起名称,属性名和set对应的名是一致的

  • 如果按照名称去找对应的bean对象,找不到则注入Null

  • 当某一个类型在IOC容器中有多个对象,按照名称注入只找其指定名称对应的bean对象,不会报错

最后对于依赖注入,需要注意一些其他的配置特征:

  1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作

  2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用

  3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用

  4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

5.4 集合注入 5.4.1、注入数组类型数据

    
        100
        200
        300
    
5.4.2、注入List类型数据

    
        itcast
        itheima
        boxuegu
        chuanzhihui
    
5.4.3、 注入Set类型数据

    
        linxin
        china
        hunan
        hangyang
    
5.4.4、 注入Map类型数据

    
        
        
        
    
5.4.5、注入Properties类型数据

    
        china
        henan
        kaifeng
    

说明:

  • property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写、、、、标签

  • List的底层也是通过数组实现的,所以和标签是可以混用

  • 集合中要添加引用类型,只需要把标签改成标签,这种方式用的比较少

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1013356.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号