Java面试之11 道 Spring IoC ⾯试题

Q1:IoC 是什么?

IoC 即控制反转,简单来说就是把原来代码⾥需要实现的对象创建、依赖反转给容器来帮忙实现,需要创建⼀个容器并且需要⼀种描述让容器知道要创建的对象间的关系,在 Spring 中管理对象及其依赖关系是通过 Spring 的 IoC 容器实现的。

IoC 的实现⽅式有依赖注⼊和依赖查找,由于依赖查找使⽤得很少,因此 IoC 也叫做依赖注⼊。依赖注

⼊指对象被动地接受依赖类⽽不⽤⾃⼰主动去找,对象不是从容器中查找它依赖的类,⽽是在容器实例 化对象时主动将它依赖地类注⼊给它。假设⼀个 Car 类需要⼀个 Engine 的对象,那么⼀般需要需要⼿动 new ⼀个 Engine,利⽤ IoC 就只需要定义⼀个私有的 Engine 类型的成员变量,容器会在运⾏时⾃动创建⼀个 Engine 的实例对象并将引⽤⾃动注⼊给成员变量。

Q2:IoC 容器初始化过程?

基于 XML 的容器初始化

当创建⼀个 ClassPathXmlApplicationContext 时,构造⽅法做了两件事:① 调⽤⽗容器的构造⽅法为容器设置好 Bean 资源加载器。② 调⽤⽗类的路径。

⽅法设置 Bean 配置信息的定位

ClassPathXmlApplicationContext 通过调⽤⽗类 AbstractApplicationContext 的⽅法启动整个 IoC 容器对 Bean 定义的载⼊过程, refresh 是⼀个模板⽅法,规定了 IoC 容器的启动流程。在创建 IoC 容器前如果已有容器存在,需要把已有的容器销毁,保证在的 IoC 容器。

⽅法后使⽤的是新创建容器创建后通过⽅法加载 Bean 配置资源,该⽅法做两件事:① 调⽤资源加载器的⽅法获取要加载的资源。② 真正执⾏加载功能,由⼦类 XmlBeanDefinitionReader 实现。加载资源时⾸先解析配置⽂件路径,读取配置⽂件的内容,然后通过 XML 解析器将 Bean 配置信息转换成⽂档对象,之后按照 Spring Bean 的定义规则对⽂档对象进⾏解析。

Spring IoC 容器中注册解析的 Bean 信息存放在⼀个 HashMap 集合中,key 是字符串,值是BeanDefinition,注册过程中需要使⽤ synchronized 保证线程安全。当配置信息中配置的 Bean 被解析且被注册到 IoC 容器中后,初始化就算真正完成了,Bean 定义信息已经可以使⽤且可被检索。Spring IoC 容器的作⽤就是对这些注册的 Bean 定义信息进⾏处理和维护,注册的 Bean 定义信息是控制反转和依赖注⼊的基础。

基于注解的容器初始化

分为两种:① 直接将注解 Bean 注册到容器中,可以在初始化容器时注册,也可以在容器创建之后⼿动注册,然后刷新容器使其对注册的注解 Bean 进⾏处理。② 通过扫描指定的包及其⼦包的所有类处理, 在初始化注解容器时指定要⾃动扫描的路径。

Q3:依赖注⼊的实现⽅法有哪些?

构造⽅法注⼊: IoC Service Provider 会检查被注⼊对象的构造⽅法,取得它所需要的依赖对象列表, 进⽽为其注⼊相应的对象。这种⽅法的优点是在对象构造完成后就处于就绪状态,可以⻢上使⽤。缺点 是当依赖对象较多时,构造⽅法的参数列表会⽐较⻓,构造⽅法⽆法被继承,⽆法设置默认值。对于⾮ 必需的依赖处理可能需要引⼊多个构造⽅法,参数数量的变动可能会造成维护的困难。

setter ⽅法注⼊: 当前对象只需要为其依赖对象对应的属性添加 setter ⽅法,就可以通过 setter ⽅法将依赖对象注⼊到被依赖对象中。setter ⽅法注⼊在描述性上要⽐构造⽅法注⼊强,并且可以被继承, 允许设置默认值。缺点是⽆法在对象构造完成后⻢上进⼊就绪状态。

接⼝注⼊: 必须实现某个接⼝,接⼝提供⽅法来为其注⼊依赖对象。使⽤少,因为它强制要求被注⼊对象实现不必要接⼝,侵⼊性强。

Q4:依赖注⼊的相关注解

@Autowired :⾃动按类型注⼊,如果有多个匹配则按照指定 Bean 的 id 查找,查找不到会报错。

@Qualifier :在⾃动按照类型注⼊的基础上再按照 Bean 的 id 注⼊,给变量注⼊时必须搭配

@Autowired ,给⽅法注⼊时可单独使⽤。

:直接按照 Bean 的 id 注⼊,只能注⼊ Bean 类型。

:⽤于注⼊基本数据类型和 String 类型。

Q5:依赖注⼊的过程?

⽅法获取 Bean 实例,该⽅***调⽤

Bean 的功能,也是触发依赖注⼊的地⽅。

具体创建 Bean 对象的过程由 ObjectFactory 的

, doGetBean 真正实现从 IoC 容器获取

完成,该⽅法主要通过依赖注⼊进⾏处理。

⽅法⽣成 Bean 包含的 Java 对象实例和⽅法对 Bean 属性的

在 populateBean ⽅法中,注⼊过程主要分为两种情况:① 属性值类型不需要强制转换时,不需要解析属性值,直接进⾏依赖注⼊。② 属性值类型需要强制转换时,⾸先解析属性值,然后对解析后的属性值进⾏依赖注⼊。依赖注⼊的过程就是将 Bean 对象实例设置到它所依赖的 Bean 对象属性上,真正的

依赖注⼊是通过 ⽅法实现的,该⽅法使⽤了委派模式。

BeanWrapperImpl 类负责对完成初始化的 Bean 对象进⾏依赖注⼊,对于⾮集合类型属性,使⽤ JDK 反射,通过属性的 setter ⽅法为属性设置注⼊后的值。对于集合类型的属性,将属性值解析为⽬标类型的集合后直接赋值给属性。

当容器对 Bean 的定位、载⼊、解析和依赖注⼊全部完成后就不再需要⼿动创建对象,IoC 容器会⾃动为我们创建对象并且注⼊依赖。

Q6:Bean 的⽣命周期?

在 IoC 容器的初始化过程中会对 Bean 定义完成资源定位,加载读取配置并解析,最后将解析的 Bean 信息放在⼀个 HashMap 集合中。当 IoC 容器初始化完成后,会进⾏对 Bean 实例的创建和依赖注⼊过程,注⼊对象依赖的各种属性值,在初始化时可以指定⾃定义的初始化⽅法。经过这⼀系列初始化操作 后 Bean 达到可⽤状态,接下来就可以使⽤ Bean 了,当使⽤完成后会调⽤ destroy ⽅法进⾏销毁,此时也可以指定⾃定义的销毁⽅法,最终 Bean 被销毁且从容器中移除。

XML ⽅式通过配置 bean 标签中的 init-Method 和 destory-Method 指定⾃定义初始化和销毁⽅法。

注解⽅式通过 和 注解指定⾃定义初始化和销毁⽅法。

Q7:Bean 的作⽤范围?

通过 scope 属性指定 bean 的作⽤范围,包括:

① singleton:单例模式,是默认作⽤域,不管收到多少 Bean 请求每个容器中只有⼀个唯⼀的 Bean 实例。

② prototype:原型模式,和 singleton 相反,每次 Bean 请求都会创建⼀个新的实例。

③ request:每次 HTTP 请求都会创建⼀个新的 Bean 并把它放到 request 域中,在请求完成后 Bean

会失效并被垃圾收集器回收。

④ session:和 request 类似,确保每个 session 中有⼀个 Bean 实例,session 过期后 bean 会随之失效。

⑤ global session:当应⽤部署在 Portlet 容器时,如果想让所有 Portlet 共⽤全局存储变量,那么该变量需要存储在 global session 中。

Q8:如何通过 XML ⽅式创建 Bean?

默认⽆参构造⽅法,只需要指明 bean 标签中的 id 和 class 属性,如果没有⽆参构造⽅***报错。

静态⼯⼚⽅法,通过 bean 标签中的 class 属性指明静态⼯⼚,factory-method 属性指明静态⼯⼚⽅法。

实例⼯⼚⽅法,通过 bean 标签中的 factory-bean 属性指明实例⼯⼚,factory-method 属性指明实例⼯⼚⽅法。

Q9:如何通过注解创建 Bean?

把当前类对象存⼊ Spring 容器中,相当于在 xml 中配置⼀个 bean 标签。value 属性指定 bean 的 id,默认使⽤当前类的⾸字⺟⼩写的类名。

@Controller , @Service , @Repository 三个注解都是 的衍⽣注解,作⽤及属性都

是⼀模⼀样的。只是提供了更加明确语义, @Controller ⽤于表现层, @Service ⽤于业务 层, @Repository ⽤于持久层。如果注解中有且只有⼀个 value 属性要赋值时可以省略 value。

如果想将第三⽅的类变成组件⼜没有源代码,也就没办法使⽤ 进⾏⾃动配置,这种时候

就要使⽤注解。被注解的⽅法返回值是⼀个对象,将会实例化,配置和初始化⼀个新

对象并返回,这个对象由 Spring 的 IoC 容器管理。name 属性⽤于给当前

注解⽅法创建的对象

指定⼀个名称,即 bean 的 id。当使⽤注解配置⽅法时,如果⽅法有参数,Spring 会去容器查找是否有可⽤ bean对象,查找⽅式和⼀样。

Q10:如何通过注解配置⽂件?

⽤于指定当前类是⼀个 spring 配置类,当创建容器时会从该类上加载注解,value 属性⽤于指定配置类的字节码。

⽤于指定 Spring 在初始化容器时要扫描的包。basePackages 属性⽤于指定要扫描的包。⽤于加载⽂件中的配置。value 属性⽤于指定⽂件位置,如果是在类路径下需要加上 classpath。

@Import ⽤于导⼊其他配置类,在引⼊其他配置类时可以不⽤再写注解。有@Import 的是⽗配置类,引⼊的是⼦配置类。value 属性⽤于指定其他配置类的字节码。

Q11:BeanFactory、FactoryBean 和

ApplicationContext 的区别?

BeanFactory 是⼀个 Bean ⼯⼚,使⽤简单⼯⼚模式,是 Spring IoC 容器顶级接⼝,可以理解为含有

Bean 集合的⼯⼚类,作⽤是管理 Bean,包括实例化、定位、配置对象及建⽴这些对象间的依赖。BeanFactory 实例化后并不会⾃动实例化 Bean,只有当 Bean 被使⽤时才实例化与装配依赖关系,属于延迟加载,适合多例模式。

FactoryBean 是⼀个⼯⼚ Bean,使⽤了⼯⼚⽅法模式,作⽤是⽣产其他 Bean 实例,可以通过实现该接⼝,提供⼀个⼯⼚⽅法来⾃定义实例化 Bean 的逻辑。FactoryBean 接⼝由 BeanFactory 中配置的对象实现,这些对象本身就是⽤于创建对象的⼯⼚,如果⼀个 Bean 实现了这个接⼝,那么它就是创建对象的⼯⼚ Bean,⽽不是 Bean 实例本身。

ApplicationConext 是 BeanFactory 的⼦接⼝,扩展了 BeanFactory 的功能,提供了⽀持国际化的⽂本消息,统⼀的资源⽂件读取⽅式,事件传播以及应⽤层的特别配置等。容器会在初始化时对配置的

Bean 进⾏预实例化,Bean 的依赖注⼊在容器初始化时就已经完成,属于⽴即加载,适合单例模式,⼀般推荐使⽤。

最后呢,本文章的所有知识取自于B站高淇老师讲的Java300集教程,里面更加全面的讲述了关于Java面试中所能遇到的各种问题,包括解决问题的方法。小编也给大家准备了充分的资源:给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1qL411u7eEicon-default.png?t=M7J4https://www.bilibili.com/video/BV1qL411u7eE

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值