spring中ioc的三种实现机制(Spring框架核心之一IOC)

前言

本文将用通俗易懂的文字介绍 Spring 的核心IoC,主要从面试的角度介绍IoC的相关知识,希望能帮助初学者快速了解 IoC,同时也是为了自己学习的过程做总结。

什么是IOC?

Inversion of Control即控制反转,简称IOC,是指将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁)和对象间的依赖关系。在传统方式下我们创建对象一般是通过new()来操作,当对象之间有依赖关系时,需要手动创建依赖对象并对其设置,使用完后还需要销毁,业务量大的情况下,这无疑是一件另开发者头痛的事情。而 IoC 则是由专门的容器来帮忙创建对象,将所有的类都在 Spring 容器中登记,由Spring管理对象的生命周期,当需要某个对象时,不再需要自己主动去 new 了,只需告诉 Spring 容器,然后 Spring 就会在系统运行到适当的时机,把你想要的对象主动给你,它解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健。

什么是DI?

Dependency Injection即依赖注入,简称DI,依赖注入不完全等同于 IoC,更应该说 DI 依赖注入是 IoC 的一种实现方式或策略。在程序运行时动态地向某个对象提供它所需要的其他对象,即应用程序在运行时依赖 IoC 容器来动态注入对象所需要的外部依赖,具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。

什么是Bean?

被称作 Bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由容器提供的配置元数据创建的

Bean的作用域:

Spring通过@scope注解设置Bean的作用域,缺省情况下默认是singleton;

spring中ioc的三种实现机制(Spring框架核心之一IOC)(1)

Spring框架中的Bean是线程安全的吗?

不是。Spring容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。

原型Bean(prototype):每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。

单例Bean(singleton):对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。

Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理。

有状态Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。 无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。

实际上大部分时间Bean是无状态的(比如Dao) 所以说在某种程度上来说Bean其实是安全的。  但是如果Bean是有状态的 那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。

@scope改为protopyte后Bean的线程就一定安全吗?

不一定。当Bean也就是平常说的@Controller,@Service,@Dao中存在static变量时,线程是不安全的。

解决办法:采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量

Spring注入bean有几种方式?
  • set方法注入
  • 构造器注入
  • 静态工厂注入
  • 实例工厂注入
Spring的自动装配

自动装配与依赖注入的关系:依赖注入的本质就是装配,装配是依赖注入的具体行为,自动装配是为了将依赖注入“自动化”的一个简化配置的操作

自动装配就是指 Spring 容器在不使用 <constructor-arg> 和<property> 标签的情况下,可以自动装配(autowire)相互协作的 Bean 之间的关联关系,将一个 Bean 注入其他 Bean 的 Property 中。

Spring中实现自动装配的方式有两种,一种是通过xml文件、一种是通过注解的方式。

自动装配的4种策略:

  • byName:根据Bean的名字进行自动装配。
  • byType:根据Bean的类型进行自动装配。
  • constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
  • autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
注入bean的注解

@Autowired:

@Autowired是 Spring 提供的注解,默认通过byType方式注入,唯一的required参数默认是true,表示开启自动装配,byName需要与@Qualifier("对象名")联用。

@Resource:

@Resource 是jdk中定义的注解,依靠的是java的标准,其中最重要的两个参数是:name 和 type,如果指定了name,则根据name自动装配,如果指定了type,则用type自动装配。

@Qualifier:

当创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,可以使用 @Qualifier 注解和 @Autowired 注解通过指定哪一个真正的 bean 将会被装配来消除混乱。

声明Bean的注解

@Componnet:通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于 哪一个层,可以使用@Component注解标注

@Repository:一般用于持久层,即Dao层,主要用于数据库相关操作

@Service:一般用于服务层,即Service层,主要涉及一些复杂的逻辑需要用到Dao层

@Controller:一般用于控制层Controller,用于与前端交互

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页