Spring IOC 学习笔记
1.引言:
本文是Spring 官方文档的学习总结,详见原文:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans
IOC(Inversion of Control)即控制反转,和AOP(Aspect Oriented Programming)面向切面编程是Spring的两大核心功能组件,由于在Spring中,bean的创建和管理是交由Spring IOC container来操作的,而不是bean类本身来控制的,因此这个过程叫做控制反转(IOC),相应的控制管理bean的container(对象)也就被称为IOC container,Spring中IOC是通过Spring IOC container来实现的,主要是用来解决bean的资源管理和依赖注入等问题。下面主要围绕ioc container是如何处理bean资源管理,依赖注入以及循环依赖等问题来讨论。
2.Spring IOC Container:
2.1概述
如引言所说,IOC Container是用来管理bean和解决依赖注入等问题的。BeanFactory接口提供了管理Bean的操作,是Spring提供的最基础的管理Bean的方法,而ApplicationContext继承于BeanFactory,同时ApplicationContext还提供了更多企业框架上的功能,, 而IOC container可以通过继承BeanFactory或者ApplicationContext等接口来实现Bean的资源管理,在Spring API中org.springframework.beans和org.springframework.context两个包是Spring IOC container的基础,Spring IOC container默认实现了ApplicationContext接口。
ApplicationContext接口提供如下操作:
1. BeanFactory中的一些用来访问Bean的方法,继承自:ListableBeanFactory接口;
2. 通用的文件加载方法,继承自ResourceLoader接口;
3. 向已注册的Listener监听器发布Event事件,继承自:ApplicationEventPublisher接口;
4. 解析消息,支持国际化,继承于MessageResource接口;
5. 继承父级context(一个Web Application有一个全局的Context,每个Servlet都有一个自己独立的child context);
一个基本的Spring IOC Container功能结构如下:

2.2加载配置
Spring IOC container该加载和管理哪些beans是通过读取配置数据来决定的,通常读取配置数据的方式有以下三种:
1).XML文件
2).anotations注解(仍需通过少量xml文件来配置支持注解)
3).java代码(constructor 参数或者setter方法)
配置数据可以用来注册和配置一些bean的基本信息(beanName,beanClass类型等),另外还可以用来配置bean之间的依赖关系。
XML方式配置方法如下(一般是应用中每个层或者模块都是一个独立的xml,例如以下的service层和dao层):
<!--services.xml-->
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- services --> <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="itemDao" ref="itemDao"/> <!-- additional collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions for services go here --> </beans>
<!-- daos.xml -->
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao"> <!-- additional collaborators and configuration for this bean go here --> </bean> <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao"> <!-- additional collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions for data access objects go here --> </beans>
然后就可以在代码中通过以下方法来获取到配置好的bean:
// create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List<String> userList = service.getUsernameList();
通过以上代码可以发现,当xml文件一旦多了,传入构造函数的参数也就多了,Spring提供如下<import />来指定resource属性进行XML文件合并(xml导入):
<!--appBeansConfig.xml-->
<beans> <import resource="services.xml"/> <import resource="resources/messageSource.xml"/> <import resource="/resources/themeSource.xml"/> <bean id="bean1" class="..."/> <bean id="bean2" class="..."/> </beans>
通过注解方式的配置方法如下:
@Configuration public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } }
上述代码等同于下面的XML形式配置:
<beans> <bean id="myService" class="com.acme.services.MyServiceImpl"/> </beans>
然后可以通过以下方法来获取bean:
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); MyService myService = ctx.getBean(MyService.class); myService.doStuff(); }
那么什么是依赖注入呢,即对象A中有一个对象B的引用,那么对象B对于对象A而言就是一个依赖。常见的依赖注入方法如下两个大的方向:
1.通过构造器来注入依赖(官方推荐方法)。
2.通过setter方法来注入依赖(可以用来解决循环依赖问题)。
其中还可以通过一些对象的工厂方法来实现(原理是一样的),关于依赖注入问题后面详细介绍。
未完待续。。。

浙公网安备 33010602011771号