Spring IOC面试

1. Spring IOC控制反转(宏观方面-设计理念)

1、IOC控制反转全称Inverse of Control,是一种设计理念
2、由代理人(水果摊老板)来创建和管理对象(苹果),消费者(消费者)通过代理人来获取对象
如消费者购买苹果,可以由中间的代理人-水果摊老板进行选择,就可以获取到需要的,而中间的过程可以由代理人来完成。消费者与对象降低了解耦
3、IOC根本目的:降低对象之间直接耦合
在这里插入图片描述

2. DI依赖注入【Dependency Injection】

1、IOC是一种设计理念,是现代程序设计遵循的标准,是宏观目标
2、DI是一种具体技术实现,是在微观编程环境下实现的(是运行时来完成对象的创建和绑定工作)
3、DI在Spring中利用反射技术和工厂模式实现对象注入
** 在程序的运行过程中反射可以让运行时的程序来进行行为的动态变化,如创建对象、设置属性、调用方法。

3. 传统开发方式与引入Spring IOC容器比较

1、传统开发方式【弊端】
对象直接引用导致对象硬性关联,程序难以维护。如果其它程序员开发了objectC对象,需要使用objectC对象就需要new 进行创建才可以使用。
​​​​在这里插入图片描述
2、引入Spring IOC容器,解决四的弊端
spring IOC容器用于统一创建和管理对象依赖。
Spring提供一个IoC容器,容器是抽象的,相当java在运行的内存中开辟一个空间,该空间是由spring管理的,所有的对象不由使用者或者A/B对象来进行创建的,而都是由Spring IoC容器统一负责创建。
而objectA是依赖objectB的,因此通过反射技术将objectA对象的依赖objectB注入到objectA对象中,而使用者提取容器中的对象进行使用。
在这里插入图片描述

4. spring IOC容器职责

1、对象的控制权交由第三方统一管理(IOC控制反转)
2、利用Java反射技术实现运行时对象创建和管理/关联(DI依赖注入)
3、基于配置提高应用程序的可维护性和扩展性

5. 对Spring的IoC理解

(1)IOC就是控制反转,指创建对象的控制权转移给Spring框架进行管理,并由Spring根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。这是宏观概念。
DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部依赖。这是微观概念,是对IOC的具体技术实现。

(2)最直观的表达就是,以前创建对象的主动权和时机都是由自己把控的,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。

(3)Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。

5.Spring中Bean及@Bean的理解

5.1 JavaBean和Bean的理解和其确保?

Bean是存放于Spring IOC容器中的对象,所以称为Bean ,而JavaBean是一种特殊的JAVA类,javaBean类实例化出的对象称之为javaBean对象。
它们的生命周期也是不一样的,Bean的生命周期由spring IOC容器来控制的,而JavaBean是不受容器来控制的。
所以,在 Spring 中,所有可以被 IOC容器 实例化并管理的 Java类 都可以称为 Bean。

5.2 Bean是什么?

1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化);
2、凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性;
3、规律:凡是子类及带有方法或属性的类都要加上注册Bean到Spring IoC的注解;
4、把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了
5、我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean或者给出一个Bean

5.3 Bean分为两类

1、一类是使用Bean
即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;
比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;
2、一类是注册Bean
如@Component , @Repository , @Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

5.4 Bean和spring的关系

在这里插入图片描述
Bean的配置信息定义了Bean的实现和依赖关系;Spring IOC容器根据Bean的配置信息,在容器内部建立Bean注册表,在根据注册表的信息来实例化Bean,并建立依赖关系;然后这些Bean实现类,放在容器中的Bean的缓冲池中,供外部调用。

6. Bean的三种配置方式

文章地址:https://blog.csdn.net/qq_33356585/article/details/88838207

6.1 基于XML配置bean

6.2 基于注解配置bean

6.3 使用java类提供Bean定义信息

7.Bean的注入

文章地址:https://blog.csdn.net/qq_33356585/article/details/88838207
xml配置:属性注入、构造函数注入和工厂方法注入
使用注解的方注入: @Autowired、@Resource和@Required

7.1 xml配置:属性注入

7.2 xml配置:构造函数注入

7.3 xml配置:工厂方法注入

静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让 spring 管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过 spring 注入的形式获取:

7.4 注解方式注入:@Autowired、@Resource和@Required

8.Spring Bean的scope(作用域)

一:bean scope(作用域)属性清单
在这里插入图片描述

  • singleton:单例模式,Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象Singleton作用域是Spring中的缺省作用域,也可以显示的将Bean定义为singleton模式。singleton在容器中为单例,存在线程安全的问题。配置为:< bean id=“userDao” class=“com.ioc.UserDaoImpl” scope=“singleton”/>
  • prototype:单例(原型)模式,每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。prototype在容器中多实例,占用更多资源,不存在线程安全问题
  • request:web环境下,在一次Http请求中,容器会返回该Bean的同一实例。而对不同的Http请求则会产生新的Bean,而且该bean仅在当前Http Request内有效。
  • session:web环境下,在一次Http Session中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效。
  • application:web环境下,ServletContext存在唯一实例。

9.Spring IOC中Bean加载过程

重点参考文章:https://blog.csdn.net/y510662669/article/details/105939021
参考文章:https://blog.csdn.net/weixin_38278878/article/details/81408403

10.Spring IOC中bean的生命周期

简单描述bean生命周期的文章:https://blog.csdn.net/github_20066005/article/details/44564681
详细描述bean生命周期的文章:https://blog.csdn.net/qq_40587575/article/details/80007257
一:Bean的生命周期图解
在这里插入图片描述
bean声明周期的容器行为和对象行为

  • 1.IOC容器准备初始化,解析xml:看一下当前applicationContext.xml文件需要创建哪些对象,为哪些对象注入什么属性,了解这些基础配置信息。
  • 2.对象实例化,执行构造方法:IOC会根据配置文件自动通过反射技术来实例化对应的bean,同时基于java的规则,执行对应的构造方法。【构造方法创建的时候,该对象还没有任何属性值】
  • 3.为对象注入属性:根据前面解析的xml知道为当前新创建的对象注入哪些属性【只有当该对象创建好之后,IOC容器才会对该对象注入数据】
  • 4.调用init-method初始化方法:当对象注入以后,IOC容器会自动调用对象的init-method方法,来完成这个对象的初始化工作。【init-method的作用就是在对象注入属性值以后,基于该属性值完成对象的初始化工作】
  • 5.IOC容器初始化完成:当xml中所有bean基于 2-3-4 步骤完成后,那IOC容器初始化工作就完成。
  • 6.执行业务代码:之后可以通过代码调用bean对象的业务代码。
  • 7.IOC容器准备销毁:当IOC容器结束的时候,IOC容器会有一个销毁的过程,就是IOC容器准备销毁。
  • 8.调用destroy-method方法释放资源:调用xml配置文件中的destroy-method方法来释放资源
  • 9.IOC容器销毁完毕:当所有bean的destroy-method方法执行完成后,IOC容器销毁完毕

注意:
ApplicationContext 接口中没有关闭容器的方法,所以使用
ApplicationContext 接口作为 IOC 容器的引用,destroy-method 将不会起到作 用 ,需 要 使 用 ApplicationContext 的 子 接 口ConfigurableApplicationContext。

详解 Bean 后置处理器:
Bean 后置处理器 : Spring 提供的特殊的 Bean
①. Bean 后置处理器允许在调用初始化方法(即:bean 节点 init-method属性对应的方法的前后)前后对 Bean 进行额外的处理.
②. Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一
实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean的属性.
③. 对 Bean 后置处理器而言, 需要实现 BeanPostProcessor 接口

二:代码
1、在pom.xml加入依赖

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.2.6.RELEASE</version>
	</dependency>
</dependencies>

2、order实体类

package com.imooc.spring.ioc.entity;

/**
 * 实体类
 */
public class Order {
    private Float price;
    private Integer quantity;
    private Float total;

    public Order(){
        System.out.println("第1步:创建(实例化)order对象,执行构造方法:" + this);
    }

    //初始化
    //在applicaltionContext.xml的
    //init-method="init",在order实体类中增加init()方法
    public void init(){
        System.out.println("第3步:执行init()方法,基于属性值完成IOC对象的初始化工作");
        total = price * quantity;
    }

    //销毁容器
    public void destroy(){
        System.out.println("第6步:销毁容器【释放与订单相关的资源,如文件、网络连接、其它系统的调用】");
    }

    //调用的方法
    public void pay(){
         System.out.println("-->订单金额为:" + total);
     }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        System.out.println("第2步:设置属性值" );
        System.out.println("-->设置price属性值:" + price);
        this.price = price;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        System.out.println("-->设置quantity属性值:" + quantity);
        this.quantity = quantity;
    }

    public Float getTotal() {
        return total;
    }

    public void setTotal(Float total) {
        this.total = total;
    }
}

3、applicationContext.xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

      <!--配置一个 bean:init-method="init",在order实体类中增加init()方法-->
      <bean id="order1" class="com.imooc.spring.ioc.entity.Order" init-method="init" destroy-method="destroy">
            <!-- 为属性赋值 -->
            <!-- 通过属性注入: 通过 setter 方法注入属性值 -->
            <property name="price" value="19.8"/>
            <property name="quantity" value="1000"/>
      </bean>
</beans>

4、主方法,测试Spring Bean对象生命周期

package com.imooc.spring.ioc;

import com.imooc.spring.ioc.entity.Order;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Spring Bean对象生命周期
 */
public class SpringApplication {

    public static void main(String[] args) {
        //1.创建Spring的IOC容器
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        System.out.println("第4步:IOC容器已初始化");
        //2.从IOC容器中获取bean的实例
        // 通过beanId(order1),获取bean对象,调用其方法和设置属性等
        Order order1 = context.getBean("order1", Order.class);
        System.out.println("第5步:执行业务代码");
		//执行业务代码
        order1.pay();
        //3.销毁IOC容器,自动执行 xml的 destroy-method 属性对应的方法
        ((ClassPathXmlApplicationContext) context).registerShutdownHook();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值