SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)

以下笔记是结合面试题来写的笔记

 一   Spring简介

1 .Spring概述

官网地址: https://spring.io/
  Spring 是最受欢迎的企业级 Java 应用程序开发框架,数以百万的来自世界各地的开发人员使用
Spring 框架来创建性能好、易于测试、可重用的代码。
Spring 框架是一个开源的 Java 平台,它最初是由 Rod Johnson 编写的,并且于 2003 6 月首
次在 Apache 2.0 许可下发布。
Spring 是轻量级的框架,其基础版本只有 2 MB 左右的大小。
Spring 框架的核心特性是可以用于开发任何 Java 应用程序,但是在 Java EE 平台上构建 web
用程序是需要扩展的。 Spring 框架的目标是使 J2EE 开发变得更容易使用,通过启用基于 POJO
编程模型来促进良好的编程实践。
面试题:
  1. 什么是 Spring 框架?

Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。

我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:核心容器中的 Core 组件是Spring 所有组件的核心,Beans 组件和 Context 组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。(2021动力节点)

2 .谈谈你对 Spring 的理解?
Spring 是一个 IOC AOP 容器框架。 Spring 容器的主要核心是:
控制反转( IOC ),传统的 java 开发模式中,当需要一个对象时,我们会自己
使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在
spring 开发模式中, spring 容器 使用了 工厂模式 为我们创建了所需要的对象,
不需要我们自己创建了,直接调用 spring 提供的对象就可以了,这是控制反
转的思想。
依赖注入( DI ), spring 使用 javaBean 对象的 set 方法或者带参数的构造方
为我们在创建所需对象时将其 属性自动设置所需要的值的过程 ,就是依赖注
入的思想。
面向切面编程( AOP ),在面向对象编程( oop )思想中,我们将事物纵向抽成
一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横
向抽成一个切面,对这个切面进行一些如 权限控制、事物管理,记录日志 等。
公用操作处理的过程就是面向切面编程的思想。 AOP 底层是 动态代理 ,如果是
接口采用 JDK 动态代理 ,如果是类采用 CGLIB 方式 实现动态代理。(2022黑马)
3 . 谈谈你对Spring的理解

Spring 是一个开源框架,为简化企业级应用开发而生。Spring 可以是使简单的JavaBean 实现以前只有EJB 才能实现的功能。Spring 是一个 IOC 和 AOP 容器框架。

Spring 容器的主要核心是:

控制反转(IOC),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在 spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用spring 提供的对象就可以了,这是控制反转的思想。

依赖注入(DI),spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。

面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用 JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。(硅谷)

2 .Spring家族

项目列表: https://spring.io/projects

3 .Spring Framework

Spring 基础框架,可以视为 Spring 基础设施,基本上任何其他 Spring 项目都是以 Spring Framework 为基础的

  3.1 Spring Framework特性

非侵入式:使用 Spring Framework 开发应用程序时, Spring 对应用程序本身的结构影响非常
小。对领域模型可以做到零污染;对功能性组件也只需要使用几个简单的注解进行标记,完全不会
破坏原有结构,反而能将组件结构进一步简化。这就使得基于 Spring Framework 开发应用程序
时结构清晰、简洁优雅。
控制反转: IOC——Inversion of Control ,翻转资源获取方向。把自己创建资源、向环境索取资源
变成环境将资源准备好,我们享受资源注入。
面向切面编程: AOP——Aspect Oriented Programming ,在不修改源代码的基础上增强代码功
能。
容器: Spring IOC 是一个容器,因为它包含并且管理组件对象的生命周期。组件享受到了容器化
的管理,替程序员屏蔽了组件创建过程中的大量细节,极大的降低了使用门槛,大幅度提高了开发
效率。
组件化: Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用 XML
Java 注解组合这些对象。这使得我们可以基于一个个功能明确、边界清晰的组件有条不紊的搭
建超大型复杂应用系统。
声明式:很多以前需要编写代码才能实现的功能,现在只需要声明需求即可由框架代为实现。
一站式:在 IOC AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库。而且
Spring 旗下的项目已经覆盖了广泛领域,很多方面的功能性需求可以在 Spring Framework 的基
础上全部使用 Spring 来实现。

3.2 Spring Framework五大功能模块

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第1张图片

面试题:

  1. 列举一些重要的Spring模块?

Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能。

Spring AOP :提供了面向切面的编程实现。

Spring JDBC : Java数据库连接。

Spring JMS :Java消息服务。

Spring ORM : 用于支持Hibernate等ORM工具。

Spring Web : 为创建Web应用程序提供支持。

Spring Test : 提供了对 JUnit 和 TestNG 测试的支持。(2021动力节点)

二  .IOC

1 .IOC容器

 1.1 IOC思想

  IOCInversion of Control,翻译过来是反转控制

之前我们需要用到某个资源 某个对象  需要我们手动去创建他  手动的去访问他  有了spring之后  可以把对象的管理权 ,对象的控制权  完全交给IOC容器   原来是主动获取  现在是被动去接受   spring为我们提供的对象  总结一句话:原来我们要自己创建 现在不用自己  用spring里面的就可以

①获取资源的传统方式
自己做饭:买菜、洗菜、择菜、改刀、炒菜,全过程参与,费时费力,必须清楚了解资源创建整个过程
中的全部细节且熟练掌握。
在应用程序中的组件需要获取资源时,传统的方式是组件 主动 的从容器中获取所需要的资源,在这样的
模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效
率。
②反转控制方式获取资源
点外卖:下单、等、吃,省时省力,不必关心资源创建过程的所有细节。
反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向 —— 改由容器主
动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源
的方式即可,极大的降低了学习成本,提高了开发的效率。这种行为也称为查找的 被动 形式。
DI
DI Dependency Injection ,翻译过来是 依赖注入
DI IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自于容器
的资源注入。相对于 IOC 而言,这种表述更直接。
所以结论是: IOC 就是一种反转控制的思想, 而 DI 是对 IOC 的一种具体实现。
解释:例如以三层架构为例子
controller:控制层 帮助我们处理请求和响应
service:  
dao:
controller  访问 service, service访问  dao  换句话说controller就要获取service对象  之前我们用传统方式的话  我们需要用到service, 就要自己new一个service对象  而我们现在有了反转控制(DI),不用在自己new一个service对象,我们可以提前以设置好的方式,然后被动的接受,然后利用spring注入
总结一句话:我们在传统方式在自己new 而现在我们有了spring之后   我们需要用到哪个对象  这个对象就由IOC容器为我们提供  具体的一个实现就用到我们DI的依赖注入
依赖注入解释:
我们当前用到哪个对象,spring就为哪个对象进行赋值
我们为成员变量赋值的方式有二种:set  构造器  
面试题:
1 .IOC 是什么?
IOC Inversion Of Controll ,控制反转)是一种设计思想,就是将原本在程序中
手动创建对象的控制权,交由给 Spring 框架来管理。 IOC 在其他语言中也有应
用,并非 Spring 特有。 IOC 容器是 Spring 用来实现 IOC 的载体, IOC 容器实际
上就是一个 Map(key, value) Map 中存放 的是各种对象。
将对象之间的相互依赖关系交给 IOC 容器来管理,并由 IOC 容器完成对象的注入。
这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IOC
容器就像是一个工厂一 样,当我们需要创建一个对象的时候,只需要配置好配置文
/ 注解即可,完全不用考虑对象是 如何被创建出来的。在实际项目中一个 Service
类可能由几百甚至上千个类作为它的底层,假 如我们需要实例化这个 Service ,可
能要每次都搞清楚这个 Service 所有底层类的构造函数,这 可能会把人逼疯。如果
利用 IOC 的话,你只需要配置好,然后在需要的地方引用就行了,大大增加了项目
的可维护性且降低了开发难度(2022黑马)

1.2、   IOC容器在Spring中的实现

Spring IOC 容器就是 IOC 思想的一个落地的产品实现。 IOC 容器中管理的组件也叫做 bean 。在创建
bean 之前,首先需要创建 IOC 容器。 Spring 提供了 IOC 容器的两种实现方式:
BeanFactory
这是 IOC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用。
ApplicationContext
BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用
ApplicationContext 而不是底层的 BeanFactory
ApplicationContext 的主要实现类
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第2张图片

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第3张图片

 双击shift 查找IOC的具体实现

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第4张图片

BeanFactory就是IOC容器最根本的实现

ctrl+H  查看子接口或类的继承关系

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第5张图片

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第6张图片

提问:

1.如何把对象交给IOC容器管理

2.如何获取ioc容器

3.如何从ioc容器中获得我们当前所管理的对象

 2、基于XML管理bean

 入门准备工作    com.atguigu.spring

spring管理对象, 管理的对象我们叫做组件  也叫做been 所以spring管理对象也可以叫做spring管理been

2.1 、实验一:入门案例
①创建spring_helloworld
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第7张图片
②引入依赖
jar


    
    
        org.springframework
        spring-context
        5.3.1
    
    
    
        junit
        junit
        4.12
        test
    

依赖解释:

spring-context中context是上下文的意思

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第8张图片
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第9张图片

③创建类HelloWorld

对象从类来的

public class HelloWorld {

    public void sayHello(){
        System.out.println("hello,spring");
    }

}

 现在要把HelloWorld这个类交给spring

如何交给spring 做法: 

④创建Spring的配置文件

现在的名字可以随便写 到ssm后 名字不能随便写 因为ssm创建的是一个web工程,spring不用我们自己来获取,而是由程序自动来获取的。以后的名字大部分是写applicationContext.xml
现在我们可以通过指定某个xml来获取ioc容器,所以当前名字可以随便取   为了规范  现在的名字也是用applicationContext.xml
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第10张图片

⑤在Spring的配置文件中配置bean

   
    

解释:

1 为什么要设置class:一个bean对应一个对象   对象从类来 所以我们要通过class,来设置我们当前bean所对应对象的类型

2. 解释

    把helloworld类型的对象交给IOC容器管理

 
     
⑥创建测试类测试
   @Test
    public void test(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取IOC容器中的bean
        HelloWorld helloworld = (HelloWorld) ioc.getBean("helloworld");
        helloworld.sayHello();
    }

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第11张图片

 思路:

把对象交给ioc容器来管理,我们获取ioc容器 就能够获取ioc容器中的对象,然后就可以调用对象中的方法

⑦思路
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第12张图片

⑧注意
Spring 底层默认通过反射技术调用组件类的无参构造器来创建组件对象,这一点需要注意。如果在需要
无参构造器时,没有无参构造器,则会抛出下面的异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'helloworld' defined in class path resource [applicationContext.xml]: Instantiation of bean
failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed
to instantiate [com.atguigu.spring.bean.HelloWorld]: No default constructor found; nested
exception is java.lang.NoSuchMethodException: com.atguigu.spring.bean.HelloWorld.
()

2.2、ioc容器创建对象的方式

com.atguigu.spring

①创建spring_ioc_xml

②引入依赖

jar


    
    
        org.springframework
        spring-context
        5.3.1
    
    
    
        junit
        junit
        4.12
        test
    
    
    
        mysql
        mysql-connector-java
        8.0.16
    
    
    
        com.alibaba
        druid
        1.0.31
    


③创建学生类Student      package com.atguigu.spring.pojo

package com.atguigu.spring.pojo;

public class Student {

    private Integer sid;

    private String sname;

    private Integer age;

    private String gender;

    public Student() {
    }

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

    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 + '\'' +
                '}';
    }
}
④创建spring配置文件spring-ioc.xml   这个名字可以随便起  具体原因见上面解释
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第13张图片




    
    

⑤测试IOCByXMLTest

    @Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        Student studentOne = (Student) ioc.getBean("studentOne");
        System.out.println(studentOne);
        
    }

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第14张图片

当前我们只是创建一个对象,并没有为我们对象中的成员变量赋值,所以我们可以获取到对象的 不过对象里面成员变量的值都是null

每个成员变量都有一个默认值,比如基本数据 int是0,   double是0.0   引用类型是null

ioc底层是工厂模式,因为他的基本的实现叫做BeanFactory,具体是如何帮我们创建对象 我们在没有学习spring之前,我们要创建对象我们用的是new构造方法,spring是如何帮我们创建对象?

想要获取ioc容器是通过配置文件来获取 所以是根据我们的

总结:在ioc容器中,就是通过反射+工厂模式来帮助我们创建对象,管理对象

如果把无参构造删掉 那么spring无法帮我们把对象创建出来 

因为无参构造是固定的,写法是固定的,有参构造要设置各自成员变量,然后为成员变量进行赋值,所以有参构造可以设置多种方式,可以设置多个重载的方法,里面可以有sid,或者说只有sname或是有sid和sname,所以它并不知道我们的有参构造是什么,但是他知道我们无参构造的样子,我们以后主要有反射 通过反射创建实例化对象用的都是无参构造

总上所述 如果这时我们把无参构造删除后 会出现如下问题:

Caused by: java.lang.NoSuchMethodException: com.atguigu.spring.pojo.Student.()

没有足够的方法异常,Student方法没有  所以这个报错的意思就是没有无参构造 

 
            

 总结:以后在写一个类的时候 一定要加上无参构造(宁可没有有参也要有无参,当前如果没有设置有参时 无参是默认的 总之一句话  写一个类  一定要写上无参构造)

2.3、实验二:获取bean的三种方式和注意事项

①方式一:根据 id 获取
由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象。
上个实验中我们使用的就是这种方式。
②方式二:根据类型获取
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第15张图片

    @Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
       // Student studentOne = (Student) ioc.getBean("studentOne");
        Student student = ioc.getBean(Student.class);
        System.out.println(student);
    }

注意事项:

1 .如果有二个bean 如图 不知道要获取哪一个就会报错  如下




    

    

 报错如下:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring.pojo.Student' available: expected single matching bean but found 2: studentOne,studentTwo
解释:Unique唯一  当前没有一个唯一的并发现异常   我们根据类型来获取Student对象,但是我们现在可有的有二个 studentOne,studentTwo 

总结:注意:根据类型获取bean时,要求IOC容器中有且只有一个类型匹配的bean
2 .如果一个bean都没有  




报错:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring.pojo.Student' available

当前没有足够的bean并发现异常

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第16张图片

③方式三:根据 id 和类型
    @Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        //根据id获取
       // Student studentOne = (Student) ioc.getBean("studentOne");
        //根据类型获取
        //Student student = ioc.getBean(Student.class);
        //根据id和类型
        Student student = ioc.getBean("studentOne", Student.class);
        System.out.println(student);
    }
SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第17张图片
④注意
当根据类型获取 bean 时,要求 IOC 容器中指定类型的 bean 有且只能有一个
IOC 容器中一共配置了两个:
id = "helloworldOne" class = "com.atguigu.spring.bean.HelloWorld" >
id = "helloworldTwo" class = "com.atguigu.spring.bean.HelloWorld" >
根据类型获取时会抛出异常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean
of type 'com.atguigu.spring.bean.HelloWorld' available: expected single matching bean but
found 2: helloworldOne,helloworldTwo
⑤扩展
如果组件类实现了接口,根据接口类型可以获取 bean 吗?
组件类:当前交给ioc管理所管理的类   每一个bean 就是一个组件  就是ioc所管理的对象
可以,前提是 bean 唯一
验证:
创建一个接口Person
 
           

让Student实现当前接口

SSM整合之spring笔记(IOC 获取bean的三种方式)(P063—P069)_第18张图片

    @Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        //根据id获取
       // Student studentOne = (Student) ioc.getBean("studentOne");
        //根据类型获取
        //Student student = ioc.getBean(Student.class);
        //根据id和类型
        //Student student = ioc.getBean("studentOne", Student.class);
        //这个是可以的  这个的意思是通过Student类型获取到bean之后 把获取的对象  通过向上转型  赋值给接口对象
        Person student = ioc.getBean(Student.class);
        System.out.println(student);
    }

 而我们这题的意思是如下:

    @Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        //根据id获取
       // Student studentOne = (Student) ioc.getBean("studentOne");
        //根据类型获取
        //Student student = ioc.getBean(Student.class);
        //根据id和类型
        //Student student = ioc.getBean("studentOne", Student.class);
        //这个是可以的  这个的意思是通过Student类型获取到bean之后 把获取的对象  通过向上转型  赋值给接口对象
        //Person student = ioc.getBean(Student.class);
        //通过接口类型在ioc里面匹配一个baen来进行获取
        //可以的  因为是根据类型来找 只要类型能够兼容匹配就可以
        //也就是说,我们在ioc容器中配置一个bean后  是可以通过它所继承的父类或所实现的接口 都可以来获取
        Person person = ioc.getBean(Person.class);
        System.out.println(person);

    }

如果一个接口有多个实现类,这些实现类都配置了 bean ,根据接口类型可以获取 bean 吗?
不行,因为 bean 不唯一
⑥结论
根据类型来获取 bean 时,在满足 bean 唯一性的前提下,其实只是看:『对象 instanceof 指定的类
型』的返回结果,只要返回的是 true 就可以认定为和类型匹配,能够获取到。
总结:
 * 获取bean的三种方式:
 * 1、根据bean的id获取
 * 2、根据bean的类型获取
 * 注意:根据类型获取bean时,要求IOC容器中有且只有一个类型匹配的bean
 * 若没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
 * 若有多个类型匹配的bean,此时抛出异常:NoUniqueBeanDefinitionException
 * 3、根据bean的id和类型获取
 * 结论:
 * 根据类型来获取bean时,在满足bean唯一性的前提下
 * 其实只是看:『对象 instanceof 指定的类型』的返回结果
 * 只要返回的是true就可以认定为和类型匹配,能够获取到。
 * 即通过bean的类型、bean所继承的类的类型、bean所实现的接口的类型都可以获取bean
 

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