Spring IoC容器

Spring IoC容器

谈及SpringBoot,必须要说Spring,而Spring IoC容器是Spring容器的内核。AOP、声明式事务等功能都是在此基础之上开花结果的。

一. 什么是IoC

IoC(Inverse of Control) 即控制反转。

所谓的反转,就是通过容器来控制业务对象的之间的依赖关系,而非传统实现中,由代码直接操控。这也是控制反转的概念所在:控制权由应用代码转移到了外部容器,控制权的转移,就是反转。带来的好处就是降低了业务对象的依赖程度。那么Spring是如何做的? 这就要说最重要的一个接口:BeanFactory。

二.BeanFactory

Spring通过一个配置文件描述了Bean及Bean之间的依赖关系,利用java语言的反射功能实例化Bean并创建Bean之间的依赖关系。这些工作正是IoC容器要做的。

  • Bean工厂:

com.springframework.beans.factory.BeanFactory: 是一个类工厂。但它和传统的类工厂不同,传统的类工厂仅负责构造一个或几个类的实例,而BeanFactory是类的通用工厂,它可以创建并管理各种类的对象。这些可被创建和管理的对象本身没有什么特别之处,仅是一个POJO,Spring称这些被创建和管理的Java对象为Bean。

  • 如何使用BeanFactory启动Spring IoC容器:

1.配置Bean信息

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
	<bean id="car" class="com.smart.Car"
		 init-method="myInit"
		 destroy-method="myDestory"
		 p:brand="红旗CA72"
		 p:maxSpeed="200" 
		 />  

</beans>

2.初始化后就可以获取bean:

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:com/smart/beanfactory/beans.xml");
BeanFactory bf = new XmlBeanFactory(res);
Car car = bf.getBean("car",Car.class);

通过BeanFactory启动IoC容器时,并不会初始化配置文件中定义的Bean。初始化动作发生在第一个调用时,对于单实例(singleton)的Bean来说,BeanFactory会缓存Bean实例,所以第二次使用getBean()获取Bean时,将直接从IoC容器的缓存中获取Bean实例。

值得一提的是,在初始化BeanFactory时,必须为其提供一种日志框架,这里使用Log4J,即在类路径下提供Log4J配置文件,这样启动Spring容器才不会报错。

那ApplicationContext和BeanFactory又有什么关系?

三.ApplicationContext

如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的身躯了。ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置的方式实现。

  • 如何用ApplicationContext启动IoC容器:
ApplicationContext ctx =
                new FileSystemXmlApplicationContext("com/smart/ context/beans.xml");
  • ApplicationContext启动容器和BeanFactory启动的区别:

    BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean;而ApplicationContext在初始化应用上下文时就实例化所有单实例的Bean。因此ApplicationContext的初始化时间会比BeanFactory稍长一些,

  • 基于注解的配置方式:

    通过@Configuration,见下文。

​ Spring为基于类注解的配置提供了专门的ApplicationContext实现类:AnnotationConfigApplicationContext。

四.WebApplicationContext

WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录的路径中装载配置文件,完成容器初始化工作。已经有了上面两种方式去启动Ioc容器,为什么还要设计WebApplicationContext ?

  • 目的:

    从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置到ServletContext中,以便Web应用环境可以访问Spring应用上下文。

  • 启动过程:

    WebApplicationContext的初始化方式和BeanFactory、ApplicationContext的初始化方式有所区别,因为WebApplicationContext需要ServletContext实例,也就是说它必须在拥有Web容器的前提下才能完成启动的工作。

    所以Spring通过在web.xml配置自启动的Servlet或定义Web容器监听器(ServletContextListener),借助这两者中的任何一个,就可以完成启动Spring Web应用上下文的工作。

    补充:

    Spring 2.0在WebApplicationContext中还为Bean添加了3个新的作用域:request作用域、session作用域和global session作用域。而在非Web应用的环境下,Bean只有singleton和prototype两个作用域。

小结:

上边我们讲了几种启动Spring Ioc容器的方式,本质都是通过将Bean的配置信息,映射成对象放入容器,供使用。但是如何将配置信息映射成Bean? 又是如何处理各个Bean的依赖关系?这就涉及到Bean的装配过程。

五.Bean的装配过程

Spring容器启动过程:

Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序调用。

Spring容器成功启动的必要条件:

1.Spring框架的类包都已经放到应用程序的类路径下。

2.应用程序为Spring提供完备的Bean配置信息。

3.Bean的类都已经放到应用程序的类路径下

Spring支持多种形式Bean配置方式。

  • XML配置:

    Spring 1.0仅支持基于XML的配置;

  • 注解配置:

    Spring 2.0新增基于注解配置的支持,同时还对基于XML的配置进行了优化和扩展,提供了多个命名空间;

  • Java类配置:

    Spring 2.0新增基于Java类配置的支持,同时对原来的配置方式也进行了部分优化。

xml配置:

Bean的命名
一般情况下,在配置一个Bean时,需要为其指定一个id属性作为Bean的名称。id在IoC容器中必须是唯一的,此外id的命名需要满足XML对id的命名规范(id是XML规定的特殊属性):必须以字母开始,后面可以是字母、数字、连字符、下画线、句号、冒号等完整结束(full stops)符,逗号和空格这些非完整结束符是非法的。

属性注入
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。

引用其他Bean
Spring IoC容器中定义的Bean可以相互引用,IoC容器则充当“红娘”的角色。下面创建一个新的Boss类,Boss类中拥有一个Car类型的属性。

注解配置:

@Component

Spring中提供了如下3个功能基本和@Component等效的注解,它们分别用于对DAO、Service及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解。
· @Repository:用于对DAO实现类进行标注。
· @Service:用于对Service实现类进行标注。
· @Controller:用于对Controller实现类进行标注。
在@Component之外提供这3个特殊的注解是为了让注解类本身的用途清晰化,此外Spring将赋予它们一些特殊的功能。因此,推荐使用特定的注解标注特定的Bean。

JAVA类配置:

@Configuration注解

普通的POJO只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供一个Bean的定义信息。

自动装配:

Spring IoC容器了解容器中所有Bean的配置信息,此外通过Java反射机制还可以获知实现类的结构信息(如构造函数方法的结构、属性等信息)。掌握容器中所有Bean的这些信息后,Spring IoC容器就可以按照某种规则对容器中的Bean进行自动装配,而无须通过显式方式进行配置。

在这里插入图片描述

但像很多事物一样,这个功能也是一把“双刃剑”,在减轻配置工作量的同时也造成了配置文件中Bean之间关系不清晰的问题,此外还容易引发一些潜在的错误。一般项目中不使用自动装配。

Bean的作用域:

在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域。

在这里插入图片描述

小结:

不同配置方式的比较:这3种配置文件很难说孰优孰劣,只能说它们都有自己的舞台和使用场景。

在这里插入图片描述

一般采用XML配置Dataource、SessionFactory等资源Bean,在XML中利用aop、context命名空间进行相关主题的配置。其他所有项目中开发的Bean,都通过基于注解配置的方式进行配置,即整个项目采用“基于XML+基于注解”的配置方式,很少采用基于Java类的配置方式。

六.资源加载:

在初始化的过程中,往往需要去加载bean的配置文件。Spring中为了访问不同类型的资源,必须使用相应的Resource实现类,这是比较麻烦的。是否可以在不显式使用Resource实现类的情况下,仅通过资源地址的特殊标识就可以加载相应的资源呢?

Spring提供了一个强大的加载资源的机制:

在这里插入图片描述

总结:

本文首先分析了IoC的概念,控制反转其实包含两个层面的意思,“控制”是接口实现类的选择控制权;而“反转”是指这种选择控制权从调用类转移到外部第三方类或容器的中。
BeanFactory、ApplicationContext和WebApplicationContext是Spring框架3个最核心的接口,框架中其他大部分的类都围绕它们展开、为它们提供支持和服务。Spring提供了一个强大加载资源的机制,不但能够通过“classpath:”、“file:”等资源地址前缀识别不同的资源类型,还支持Ant风格带通配符的资源地址。

最后谈了几种不同的配置方式。通过@Component及另外3 个衍型注解(@Repository、@Service及@Controller)配合@Autowired就可以很好地使用基于注解的配置进行Bean的定义和注入,这种方式比在XML文件中通过提供的配置更加简单。
任务POJO标注了@Configuration注解后就可以为Spring容器提供Bean的定义信息,在类方法中标注@Bean相当于定义了一个Bean,同时还提供了Bean的实例化逻辑。由于Bean的实例化逻辑是在方法中定义的,因此它可以应对一些复杂Bean实例化的场景。

不管使用何种配置方式,Spring都可以很好地将它们整合起来,在Spring容器内部,这些不同方式的Bean定义信息大体相同,三者之间并不存在谁替换谁的问题,它们都有自己最适合的应用场合。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值