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

目录
相关文章
|
26天前
|
XML 安全 Java
|
1月前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
48 0
|
5天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
3天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
12天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
28 5
|
23天前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
51 8
|
25天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
45 2
|
1月前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
61 6
|
1月前
|
Java 数据库连接 数据库
不可不知道的Spring 框架七大模块
Spring框架是一个全面的Java企业级应用开发框架,其核心容器模块为其他模块提供基础支持,包括Beans、Core、Context和SpEL四大子模块;数据访问及集成模块支持数据库操作,涵盖JDBC、ORM、OXM、JMS和Transactions;Web模块则专注于Web应用,提供Servlet、WebSocket等功能;此外,还包括AOP、Aspects、Instrumentation、Messaging和Test等辅助模块,共同构建强大的企业级应用解决方案。
82 2
|
1月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
34 0