spring框架-认识IOC(二)

简介: spring框架-认识IOC(二)

回顾:

spring框架-认识spring框架(一)


上一章提到的一些概念,本章会详细解读


目录


IOC是什么


IOC的优点


DL (依赖查找)


名称查找 - autowireByName


类型查找 - autowireByType


DI(依赖注入)


IOC容器


Spring容器(Bean工厂)


BeanFactory和ApplicationContext区别


Spring Bean的生命周期



装配Bean方式


依赖注入方式


构造方法注入和属性注入有什么区别


Bean的作用域


bean的自动装配


常用注解详解


总结


IOC是什么

IoC(Inversion of Control)控制反转,包含了两个方面:一、控制。二、反转


类与类依赖关系交给容器处理。IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。


IOC不够开门见山,于是Martin Fowler提出了DI(dependency injection)依赖注入来替代IoC,即让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,以移除调用类对某一接口实现类的依赖。


IOC有两种方式:DI(依赖注入)和DL (依赖查找)


IOC的优点

减少了对象的创建和管理 ,使代码层次更加清晰。

Spring 的IOC容器是一个轻量级的容器 ,没有侵入性(不依赖容器的API) ,不需要实现一些特殊接口。

鼓励我们面向接口编程。

减少了代码的耦合,将耦合的部分推到了配置文件中 ,如果他们的关系发生了改变,只需要修改配置文件。

DL (依赖查找)

程序提供查找方式,交给容器去查找(回调函数)

容器提供回调接口和上下文环境给组件。EJB和Apache Avalon都使用这种方式


下面代码展示了基于JNDI实现的依赖查找机制。


public class MyBusniessObject{

   private DataSource ds;

   private MyCollaborator myCollaborator;

 

   public MyBusnissObject(){

   Context ctx = null;

   try{

   ctx = new InitialContext();

   ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);

   myCollaborator =

   (MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);

   }……

但是日常开发中,EJB类似的已经很少用到了,所以很多同学没听过DL(依赖查找),这很正常,大家更熟悉的是DI(依赖注入)。


不过这两个查找大家应该用过:


名称查找 - autowireByName

类型查找 - autowireByType

名称查找 - autowireByName

直接从 BeanFactory 中取出这个 bean 就可以了,常用的就是@Qualifier


类型查找 - autowireByType

常用的就是@autowire

如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常

简单的理解就是通过类名去匹配


DI(依赖注入)

一个对象需要另外一个对象时,无需在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序


用图例说明一下,传统程序设计如下图1,都是主动去创建相关对象然后再组合起来:image.png

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2所示

image.pngIOC容器

IOC容器其实就是一个大工厂,它用来管理我们所有的对象以及依赖关系。


原理就是通过Java的反射技术来实现的!通过反射我们可以获取类的所有信息(成员变量、类名等等等)!

再通过配置文件(xml)或者注解来描述类与类之间的关系

我们就可以通过这些配置信息和反射技术来构建出对应的对象和依赖关系了!

Spring容器(Bean工厂)

BeanFactory:这是最基础、面向Spring的

ApplicationContext:这是在BeanFactory基础之上,面向使用Spring框架的开发者。提供了一系列的功能!

ApplicationContext这个大家就很熟悉了吧,spring绝大部分应用都是使用ApplicationContext


BeanFactory和ApplicationContext区别


BeanFactory 可以理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义,以便在接收到客户端请求时将对应的bean实例化。


BeanFactory还能在实例化对象的时生成协作类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。


applicationcontext是beanFactory的子接口,拥有BeanFactory的所有功能,但applicationcontext在此基础上还提供了其他的功能。


提供了支持国际化的文本消息

统一的资源文件读取方式

已在监听器中注册的bean的事件

且beanFactory是延迟加载,需要类的时候才创建类的实例,而ApplicationContext在初始化时就加载完成了所有的单例bean

以下是三种较常见的 ApplicationContext 实现方式:


1、ClassPathXmlApplicationContext:从classpath的XML配置文件中读取上下文,并生成上下文定义。应用程序上下文从程序环境变量中取得


   ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);  

2、FileSystemXmlApplicationContext :由文件系统中的XML配置文件读取上下文。

ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);


3、XmlWebApplicationContext:由Web应用的XML文件读取上下文。


Spring Bean的生命周期

Spring Bean的生命周期简单易懂。在一个bean实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个bean不在被调用时需要进行相关的析构操作,并从bean容器中移除。


Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。


初始化之后调用的回调方法。

销毁之前调用的回调方法。

Spring框架提供了以下四种方式来管理bean的生命周期事件:


InitializingBean和DisposableBean回调接口

针对特殊行为的其他Aware接口

Bean配置文件中的Custom init()方法和destroy()方法

@PostConstruct和@PreDestroy注解方式

使用customInit()和 customDestroy()方法管理bean生命周期的代码样例如下:


image.png

<beans> 
    <bean id="demoBean" class="com.somnus.task.DemoBean" init-method="customInit"     destroy-method="customDestroy">
    </bean> 
</beans> 

装配Bean方式

Spring4.x开始IOC容器装配Bean有4种方式:


XML配置

注解

JavaConfig

基于Groovy DSL配置(这种很少见)

日常开发中,常用到的是XML配置+注解。


剩下的两种有兴趣的可以自行百度+google


依赖注入方式

依赖注入的方式有3种方式:


属性注入-->通过setter()方法注入

构造方法注入

工厂方法注入

构造方法注入和属性注入有什么区别

在属性注入方法支持大部分的依赖注入,如果我们仅需要注入int、string和long型的变量,我们不要用设值的方法注入。对于基本类型,如果我们没有注入的话,可以为基本类型设置默认值。在构造方法注入不支持大部分的依赖注入,因为在调用构造方法中必须传入正确的构造参数,否则的话为报错。

属性注入不会重写构造方法的值。如果我们对同一个变量同时使用了构造方法注入又使用了设置方法注入的话,那么构造方法将不能覆盖由设值方法注入的值。很明显,因为构造方法尽在对象被创建时调用。

在使用属性注入时有可能还不能保证某种依赖是否已经被注入,也就是说这时对象的依赖关系有可能是不完整的。而在另一种情况下,构造器注入则不允许生成依赖关系不完整的对象。

在属性注入时如果对象A和对象B互相依赖,在创建对象A时Spring会抛出sObjectCurrentlyInCreationException异常,因为在B对象被创建之前A对象是不能被创建的,反之亦然。所以Spring用设值注入的方法解决了循环依赖的问题,因对象的设值方法是在对象被创建之前被调用的。

Bean的作用域

Spring容器中的bean可以分为5个范围。所有范围的名称都是自说明的,但是为了避免混淆,还是让我们来解释一下:


使用3,4,5作用域的,需要手动设置代理


singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。

prototype:多例范围与单例范围相反,为每一个bean请求提供一个实例。

request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。

Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。

global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

bean的自动装配

使用bean元素的autowire属性来指定Bean定义的自动装配,共有5中模式:


no   默认的方式是不进行自动装配,通过手工设置ref 属性来进行装配bean

byName   依赖的 bean 名称需要与类中引用的名称一致  ,就会匹配依赖关系,我们在类中的引用的名称是 userAutowireDao 所以就会去匹配我们的 userAutowireDao 方法

byType   通过参数的数据类型自动自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配,简单的理解就是通过类名去匹配

construct   构造方法中的参数通过byType的形式,自动装配。

default 由上级标签<beans>的default-autowire属性确定。

常用注解详解

注解注入就是用注解标签的方式来替换掉我们 xml 配置文件里面 bean 的注册和依赖


@Component


用于类上

所有的类上面都可以这么写,通用注解,这是不规范的写法,哈哈哈image.pngimage.png@Resource


用于类内

javaEE 的注解 ,默认是以 byName 方式注入,byName 找不到的话,再用 byType 去匹配

效果跟Autowired一样,查找顺序相反

@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

image.pngimage.png@Autowired


用于类内

spring 的注解,默认是以 byType 注入,-如果有多个实现类,他再用 byName 的方式(@Qualifier)去匹配

效果跟Resource一样,查找顺序相反

Autowired和Qualifier一起用,

eg:

@Autowired

@Qualifier(value = "TestService2")

private TestService testService;

//实现类

@Service("TestService1")

public class TestServiceImpl implements TestService {...}

//实现类

@Service("TestService2")

public class TestServiceImpl implements TestService {...}

image.png@Scope


bean的作用域,可以查看上面的概念,这里就不再重复了


总结

借鉴了其他博主的思路:会整理出Spring思维导图出来,等AOP写好一并放出来。


今天的spring介绍就写到这里,再见!


参考资料:


《精通Spring4.x 企业应用开发实战》

https://my.oschina.net/u/3777556/blog/1816921--Spring IOC知识点一网打尽!


https://www.zhihu.com/question/48427693?sort=created--怎么回答面试官:你对Spring的理解


https://www.cnblogs.com/liangyihui/p/5917773.html--最全的Spring面试题和答案


https://blog.csdn.net/sunqingzhong44/article/details/51983620--spring笔记——bean自动装配的5种模式(autowrite属性)



image.png

目录
相关文章
|
2天前
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
16 1
|
6天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
27 2
|
6天前
|
Cloud Native 安全 Java
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
35 2
|
8天前
|
JavaScript 前端开发 Java
【颠覆传统】Spring框架如何用WebSocket技术重塑实时通信格局?揭秘背后的故事与技术细节!
【9月更文挑战第4天】随着Web应用对实时交互需求的增长,传统的HTTP模型已无法满足现代应用的要求,特别是在需要持续、双向通信的场景下。WebSocket协议由此诞生,提供全双工通信渠道,使服务器与客户端能实时互发消息。作为Java开发中最受欢迎的框架之一,Spring通过其WebSocket模块支持这一协议,简化了WebSocket在Spring应用中的集成。
28 0
|
11天前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
15 0
|
11天前
|
消息中间件 Kafka Java
Spring 框架与 Kafka 联姻,竟引发软件世界的革命风暴!事件驱动架构震撼登场!
【8月更文挑战第31天】《Spring 框架与 Kafka 集成:实现事件驱动架构》介绍如何利用 Spring 框架的强大功能与 Kafka 分布式流平台结合,构建灵活且可扩展的事件驱动系统。通过添加 Spring Kafka 依赖并配置 Kafka 连接信息,可以轻松实现消息的生产和消费。文中详细展示了如何设置 `KafkaTemplate`、`ProducerFactory` 和 `ConsumerFactory`,并通过示例代码说明了生产者发送消息及消费者接收消息的具体实现。这一组合为构建高效可靠的分布式应用程序提供了有力支持。
38 0
|
11天前
|
Java Spring 人工智能
AI 时代浪潮下,Spring 框架异步编程点亮高效开发之路,你还在等什么?
【8月更文挑战第31天】在快节奏的软件开发中,Spring框架通过@Async注解和异步执行器提供了强大的异步编程工具,提升应用性能与用户体验。异步编程如同魔法,使任务在后台执行而不阻塞主线程,保持界面流畅。只需添加@Async注解即可实现方法的异步执行,或通过配置异步执行器来管理线程池,提高系统吞吐量和资源利用率。尽管存在线程安全等问题,但异步编程能显著增强应用的响应性和效率。
23 0
|
11天前
|
测试技术 Java Spring
Spring 框架中的测试之道:揭秘单元测试与集成测试的双重保障,你的应用真的安全了吗?
【8月更文挑战第31天】本文以问答形式深入探讨了Spring框架中的测试策略,包括单元测试与集成测试的有效编写方法,及其对提升代码质量和可靠性的重要性。通过具体示例,展示了如何使用`@MockBean`、`@SpringBootTest`等注解来进行服务和控制器的测试,同时介绍了Spring Boot提供的测试工具,如`@DataJpaTest`,以简化数据库测试流程。合理运用这些测试策略和工具,将助力开发者构建更为稳健的软件系统。
21 0
|
11天前
|
容器 Java Spring
Spring框架遇上Docker:传统与现代的碰撞,谁将重塑应用部署的未来?
【8月更文挑战第31天】Spring框架凭借其强大的企业级特性和便捷的开发模式,在Java开发中占据重要地位。Docker作为容器化技术的代表,提供了轻量级、可移植的应用部署解决方案。两者结合,尤其在微服务架构中,能显著提升开发效率、部署速度和环境一致性。
28 0
|
11天前
|
Java Spring 自然语言处理
Spring 框架里竟藏着神秘魔法?国际化与本地化的奇妙之旅等你来揭开谜底!
【8月更文挑战第31天】在软件开发中,国际化(I18N)与本地化(L10N)对于满足不同地区用户需求至关重要。Spring框架提供了强大支持,利用资源文件和`MessageSource`实现多语言文本管理。通过配置日期格式和货币符号,进一步完善本地化功能。合理应用这些特性,可显著提升应用的多地区适应性和用户体验。
24 0