Spring框架学习笔记,超详细!!(1)

Java小白开始学习Spring框架,一方面,跟着视频学习,并记录下学习笔记,方便以后复习回顾。另一方面,发布学习笔记来约束自己,学习路程还很遥远,继续加油坚持!!!希望能帮助到大家!

本期更新Spring、Spring对IoC的实现、Bean的作用域等相关知识点。

另外还有我的牛客Java专项练习笔记专栏也在同步更新,希望大家多多关注,一起学习!!!

1. 前期

1.1 开闭原则 OCP

  • 什么是OCP:

  • OPC是软件七大开发原则中最基本的一个原则,开闭原则

  • 对什么开? 对扩展开放

  • 对什么闭? 对修改关闭

  • OCP原则是最核心的,最基本的,其他的六个原则都是为这个原则服务的

  • OCP开闭原则的核心:

  • 只要在扩展系统功能的时候,没有修改以前写好的代码

1.2 依赖倒置原则 DIP

  • 什么是DIP:

  • 倡导面你想想接口编程,面向抽象编程,不要面向具体编程

  • 目的:

  • 降低程序的耦合度,提高扩展力

  • 什么叫违背依赖倒置

  • 上 依赖 下,就是违背

  • 只要 下 一改动,上 就受到牵连

1.3 当前程序既违反OCP又违反DIP,怎么办?

  • 可以采取“控制反转”这种思想来解决

1.4 控制反转 IoC

  • 控制反转:IoC

  • 反转的是什么?

  • 不在程序中采用硬编码的方式来new对象了(new对象不管了,new对象的权力交出去)

  • 不在程序中采用硬编码的方式来维护对象的关系了(对象之间关系的维护权也交出去)

  • 是一种编程思想,或者叫一种新型的设计模式(没有包括在23种设计模式内)

1.5 Spring框架

  • Spring框架实现了控制反转IoC思想

  • Spring框架可以帮助我们new对象

  • Spring框架可以帮我们维护对象和对象之间的关系

  • Spring是一个实现了IoC思想的容器

  • 控制反转的实现方式由多种,比较重要的叫做:依赖注入(Dependency Injection, DI)

  • 控制反转是思想,依赖注入是这种思想的具体实现

  • 依赖注入DI,包括两种方式

  • set注入(执行set方法给属性赋值)

  • 构造方法注入(执行构造方法给属性赋值)

  • “依赖”是什么?“注入”是什么?

  • 依赖:A对象和B对象的关系

  • 注入:是一种手段,可以让A对象和B对象产生关系

  • 依赖注入,A对象和B对象之间的关系,靠注入的手段来维护

2. Spring

2.1 Spring5概述

  • 作用:

  • 简化开发,降低企业开发复杂性

  • 框架整合,高效的整合其他技术,提高企业及应用开发与运行效率

  • Spring5系统架构图

Spring框架学习笔记,超详细!!(1)_第1张图片
  • Core Container

Core Container模块包含Beans、Core、Context和Expression Language模块
Core和Beans模块是框架的基础部分, 提供IoC(控制反转)和依赖注入特性
Core模块主要是包含Spring框架基本的核心工具类,Spring的其他组件都要用到在这个类,Core模块是其他组件的基本核心
Beans模块是所有应用都要应用的,它包含配置文件、创建和管理bean以及进行IoC/DI操作相关的所有类
Context模块构建于Core和Beans模块基础之上,提供了一种类似于JNDI注册器的框架式的对象访问方法。Context模块继承了Beans的特性,为Spring提供了大量扩展,添加了对国际化(例如资源绑定)、事件传播、资源加载和对Context的透明创建的支持
Expression Language模块提供了强大的表达式语言,用于在运行时查询的操纵对象
  • Data Access/Integration

Data Access/Integration包含JDBC、ORM、OXM、JMS和Transaction模块
JDBC模块提供了一个JDBC抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码。这个模块包含了Spring对JDBC数据访问进行封装的所有类
ORM模块为流行的对象-关系映射API。利用ORM封装包,可以混用使用所有Spring提供的特性进行O/R映射,例如Mybatis
OXM模块提供了一个对Object/XML映射实现的抽象层,Object/XML映射映射实现包括JAXB、Castor、XMLBeans、JiBX和XStream
JMS模块种族要包含一些制造和消费信息的特性
Transaction模块支持编程和声明性的事务管理,这些事务必实现特定的接口,并对所有的POJO都适用
  • Web

Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文, Web层包含了Web、Web-Servlet、MVC框架和Web-Porlet模块
Web模块基础 Web 功能,如多文件上传、集成 IoC 容器、远程过程访问(RMI、Hessian、Burlap)以及 Web Service 支持,并提供了 RestTemplate 类来进行 Restful Services 访问。
Servlet模块提供了 Spring MVC Web 框架实现。Spring MVC 框架提供了基于注解的请求资源注入,可以更简单地进行数据绑定、数据验证和一套非常易用的 JSP 标签,完全无缝地与其他 Spring 技术进行协作。
MVC框架模块提供了与常用 MVC 开发框架的整合,如 Struts、JSF 等。
Porlet模块是一个基于 Web 的应用,它能提供个性化、单点登录、不同源的内容聚合和信息系统的表示层集中。聚合是整合不同 Web 页面源数据的过程。
  • AOP

符合 AOP Alliance 规范的面向切面编程实现,提供了如日志记录、权限控制、性能统计等通用功能和业务逻辑分离技术,能动态地把这些功能添加到需要的代码中,从而降低业务逻辑和通用模块的耦合。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过Spring AOP,不用依赖EJB组件,就可以将声明式事务管理集成到应用程序中。
  • Aspects

Aspects模块提供了对AspectJ的集成支持
  • Instrumentation

是 Java 5 之后提供的特性。使用 Instrumentation,开发者可以构建一个代理,用来监测运行在 JVM 上的程序。监测一般是通过在执行某个类文件之前,对该类文件的字节码进行适当修改进行的。
  • Messaging

从Spring开始新机爱如的一个模块,主要职责是为Spring框架集成一些基础的报文传送应用
  • Test

支持 JUnit 和 Test 测试框架,而且额外提供了一些基于 Spring 的测试功能。例如,可在测试 Web 框架时模拟 HTTP 请求功能。或者启动容器,实现依赖注入管理。

2.2 Spring6架构

Spring框架学习笔记,超详细!!(1)_第2张图片

特点:

  • 轻量

  • 从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。

  • Spring是非侵入式的:Spring应用中的对象不依赖于Spring的特定类。

  • 控制反转

  • Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

  • 面向切面

  • Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

  • 容器

  • Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

  • 框架

  • Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

2.3 Spring入门案例

2.3.1 IOC实现步骤
  • 实现步骤

  1. 导入Spring坐标

  1. 定义Spring管理的类(接口)

  1. 创建Spring配置文件,配置对应类(实现类)作为Spring管理的bean对象

  1. 初始化IoC容器(Spring核心容器/Spring容器),通过容器去获取bean对象

2.3.2 IOC实现代码

【第一步】导入Spring坐标


    
    
        org.springframework
        spring-context
        XXXXXXXXX
    

【第二步】定义Spring管理的类(接口)

  • BookDao接口和BookDaoImpl实现类

public interface BookDao {
    public void save();
}

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
}
  • BookService接口和BookServiceImpl实现类

public interface BookService {
    public void save();
}

public class BookServiceImpl implements BookService {
    private BookDao bookDao = new BookDaoImpl();
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

【第三步】创建Spring配置文件,配置对应类(实现类)作为Spring管理的bean对象

  • 定义applicationContext.xml配置文件(resources文件下)并配置BookServiceImpl



 
    
    

【第四步】初始化IoC容器(Spring核心容器/Spring容器),通过容器去获取bean对象

public class App {
    public static void main(String[] args) {
        //
        
        //1.创建IoC容器对象,加载spring核心配置文件
        //相当于启动了Spring容器,并实例化所有的bean对象,放到spring容器当中
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //2 从IOC容器中获取Bean对象(BookService对象)
        BookService bookService= (BookService)ctx.getBean("bookService");
        
        //3 调用Bean对象(BookService对象)的方法
        bookService.save();
    }
}

运行结果

2.3.3 DI实现步骤
  • 实现步骤

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

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

  1. 配置service与dao之间的关系

2.3.4 DI实现代码

【第一步】删除使用new形式创建对象的代码

public class BookServiceImpl implements BookService {
    private BookDao bookDao;  //【第一步】删除使用new的形式创建对象的代码
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

【第二步】提供依赖对象对应的setter方法

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
    //【第二步】提供依赖对象对应的setter方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

【第三步】配置service与dao之间的关系

在applicationContext.xml中配置



    
    

    
        
        
    

图解演示

Spring框架学习笔记,超详细!!(1)_第3张图片
2.3.5 细节
  • bean标签的id属性不能重复

  • 默认底层是通过反射调用无参构造方法创建对象

// dom4j解析beans.xml文件,从中获取class的全限定类名
// 通过反射机制调用无参数构造方法创建对象
Class clazz = Class.forName("com.powernode.spring6.bean.User");
Object obj = clazz.newInstance();
  • 如果bean的id不存在,不会返回null,而会直接报错

  • getBean()方法返回的类型是Object,如果访问子类的特有属性和方法时,还需要向下转型(强转)

User user = (User)applicationContext.getBean("userBean");

User user = applicationContext.getBean("userBean", User.class);
  • ApplicationContext的超级父类接口BeanFactory

BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
Object vipBean = beanFactory.getBean("vipBean");
System.out.println(vipBean);

BeanFactory是Spring容器的超级接口。ApplicationContext是BeanFactory的子接口

3. Spring对IoC的实现

3.1 IoC控制反转

  • 控制反转是一种思想

  • 控制反转是为了降低程序耦合度,提高程序扩展能力,达到OCP原则,DIP原则

  • 控制反转,反转的是什么?

  • 将对象的创建权力交出去,交给第三方容器负责

  • 将对象和对象之间的关系的维护权交出去,交给第三方容器负责

  • 控制反转这种思想通过依赖注入(DI)实现

3.2 依赖注入

依赖注入实现了控制反转的思想。

Spring通过依赖注入的方式来完成Bean管理的。

Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。

依赖注入:

  • 依赖指的是对象和对象之间的关联关系。

  • 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。

依赖注入常见的实现方式包括两种:

  • 第一种:set注入

  • 第二种:构造注入

3.2.1 set注入
  • 引用类型:使用ref属性

Spring框架学习笔记,超详细!!(1)_第4张图片
  • 简单类型:使用value属性

Spring框架学习笔记,超详细!!(1)_第5张图片
  • set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系。

3.2.2 构造注入
  • 引用类型

Spring框架学习笔记,超详细!!(1)_第6张图片
  • 简单类型

Spring框架学习笔记,超详细!!(1)_第7张图片
  • 核心原理:通过调用构造方法来给属性赋值

  • 如果构造方法有多个参数

Spring框架学习笔记,超详细!!(1)_第8张图片
3.2.3 set注入简单类型
  • 如果给简单类型赋值,使用value属性或标签

  • 简单类型:

  • 基本数据类型

  • 基本数据类型对应的包装类

  • String或其他的CharSequence子类

  • Number子类

  • Enum子类

  • URI

  • URL

3.2.4 注入数组类型数据



    
        
            
                鸡排
                汉堡
                鹅肝
            
        
    
3.2.5 注入List类型数据

    
        itcast
        itheima
        boxuegu
        chuanzhihui
    
3.2.6 注入Set类型数据

    
        itcast
        itheima
        boxuegu
        boxuegu
    
3.2.7 注入Map类型数据

    
        
        
        
        
        
    
3.2.8 注入Properties类型数据

    
        china
        henan
        kaifeng
    
3.2.9 P命名空间注入
  • 使用条件包括两个:

  • 在XML头部信息中加入p命名空间的配置信息:xmlns:p="http://www.springframework.org/schema/p"

  • p命名空间注入是基于setter方法的,所以需要对应的属性提供setter方法。




    

3.2.10 c命名空间注入
  • 使用条件包括两个:

  • 在XML头部信息中加入p命名空间的配置信息:xmlns:c="http://www.springframework.org/schema/c"

  • 需要提供构造方法




    

    

3.2.11 util命名空间注入
  • 使用util命名空间可以让配置复用




    
        com.mysql.cj.jdbc.Driver
        jdbc:mysql://localhost:3306/spring
        root
        1234
    

    
        
    

    
        
    
3.2.12 自动装配
  • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

  • 自动装配方式

==按类型(常用)==

按名称

按构造方法

不启用自动装配

依赖自动装配

配置中使用bean标签autowire属性设置自动装配的类型

依赖自动装配特征

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

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

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

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

  1. 无论是byName还是byType,在装配的时候都是基于set方法的。所以set方法是必须要提供的。提供构造方法是不行的。

3.2.13 Spring引入外部属性配置文件

编写数据源的时候是需要连接数据库的信息的,例如:driver url username password等信息。这些信息可以单独写到一个属性配置文件中吗,这样用户修改起来会更加的方便.

【第一步】写一个数据源类,提供相关属性

public class MyDataSource implements DataSource {
    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    private String driver;
    private String url;
    private String username;
    private String password;

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    //......
}

【第二步】在类路径下新建jdbc.properties文件,并配置信息

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring
username=root
password=1234

【第三步】在spring配置文件种引用context命名空间,使用标签context:property-placeholder的location属性类指定属性配置文件的路径,默认从根路径下开始加载资源




    

【第四步】在spring中配置使用jdbc.properties文件




    
    
    
        
        
        
        
    

4. Bean的作用域

4.1 singleton

  • Spring默认情况下偶是如何管理Bean的:

  • 默认情况下Bean是单例的

  • spring上下文初始化的时候实例化

  • 每一次调用getBean()方法的时候,都会返回单例对象

  • 示例:




    

public class AppForScope {
    public static void main(String[] args) {
        //3.获取IoC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //4.获取bean
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        System.out.println(bookDao);
        System.out.println(bookDao1);
    }
}
  • 输出结果

4.2 prototype

如果想让Spring的Bean对象以多例的形式存在,可以在bean标签中指定scope属性的值为:prototype,这样Spring会在每一次执行getBean()方法的时候创建Bean对象,调用几次则创建几次。

  • 示例




    

public class AppForScope {
    public static void main(String[] args) {
        //3.获取IoC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //4.获取bean
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        System.out.println(bookDao);
        System.out.println(bookDao1);
    }
}
  • 输出结果

4.3 其他scope

scope属性的值不止两个,它一共包括8个选项:

  • singleton:默认的,单例。

  • prototype:原型。每调用一次getBean()方法则获取一个新的Bean对象。或每次注入的时候都是新对象。

  • request:一个请求对应一个Bean。仅限于在WEB应用中使用。

  • session:一个会话对应一个Bean。仅限于在WEB应用中使用。

  • global session:portlet应用中专用的。如果在Servlet的WEB应用中使用global session的话,和session一个效果。(portlet和servlet都是规范。servlet运行在servlet容器中,例如Tomcat。portlet运行在portlet容器中。)

  • application:一个应用对应一个Bean。仅限于在WEB应用中使用。

  • websocket:一个websocket生命周期对应一个Bean。仅限于在WEB应用中使用。

  • 自定义scope:很少使用。

你可能感兴趣的:(Spring框架学习笔记,spring,java,后端,架构)