Spring IOC容器学习总结

1. Spring Ioc容器

       Spring容器是Spring框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans。

       IOC(Inversion of Control):控制反转(也称依赖倒置),是一种设计思想,也是容器。

       IOC容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFactory是IOC容器的实际代表者。

       Spring IOC容器学习总结_第1张图片
       Spring 提供了以下两种不同类型的容器。

容器 描述
BeanFactory 它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。
ApplicatoinContext 该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。

注1:BeanFactory和ApplicatonContext是Spring的两大核心接口。
注2:ApplicationContext是BeanFactory的子接口,它们都可以代表Spring容器。
注3:ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常不建议使用BeanFactory。但BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。
注4:IOC容器不只是Spring才有,很多框架也都有该技术。


1.1. BeanFactory接口

       Spring容器最基本的接口是:BeanFactory,负责配置、创建、管理Bean,还负责管理Bean与Bean之间的依赖关系。

BeanFactory接口包含如下几个基本方法:

       boolean containsBean(String name)
              判断Spring容器是否包含id为name的Bean对象。

        T getBean(Class requiredType)
              获取Spring容器中属于requiredType类型的、唯一的Bean对象。

       Object getBean(String name)
              返回容器id为name的Bean对象。

        T getBean(String name, Class requiredType)
              返回容器中id为name,并且类型为requiredType的Bean。

       Class getType(String name)
              返回容器中id为name的Bean实例的类型。


       Spring IOC容器的实现,从根源上是BeanFactory,但真正可以作为一个可以独立使用的IOC容器还是DefaultListableBeanFactory,因此可以这么说,DefaultListableBeanFactory是整个Spring IOC的始祖。
       Spring IOC容器学习总结_第2张图片

1.2. ApplicationContext接口

       ApplicationContext是BeanFactory的子接口,具有BeanFactory所有的功能。大部分时候,都不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器。

       ApplicationContext称为Spring上下文,如果说BeanFactory是心脏,那么ApplicationContext就是身躯。

最常用的ApplicationContext接口实现类:

  • FileSystemXmlApplicationContext:该容器从XML文件中加载已被定义的bean。这里需要XML的完整路径。
// 当前路径加载单个配置文件
ApplicationContext  ctx = new FileSystemXmlApplicationContext("applicationContext.xml");

// 同时加载多个配置文件
String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new FileSystemXmlApplicationContext(locations );

// 根据具体路径加载文件
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:/project/bean.xml");
  • ClassPathXmlApplicationContext:同上,不需要XML的完整路径。
// 加载单个配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");

// 同时加载多个配置文件
String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new ClassPathXmlApplication(locations);

// 或者用通配符同时加载多个配置文件:
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:/*.xml");

       注:其中FileSystemXmlApplicationContext和ClassPathXmlApplicationContext与BeanFactory的xml文件定位方式一样是基于路径的。

  • WebXmlApplicationContext:该容器会在一个Web项目的范围内加载XML中已被定义的bean。
ServletContext servletContext = request.getSession().getServletContext();

ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

面试题:
ClassPathXmlApplicationContext和FileSystemXmlApplicationContext的区别如下:
(1)Classpath:前缀是不需要的,默认就是指项目的classpath路径下面。
(2)如果要使用绝对路径,需要加上file:前缀表示这是绝对路径。

1.3. 关于控制反转的一些事儿

       Spring IOC容器学习总结_第3张图片
       在Java项目开发中,IOC意味着将你设计好的对象交给容器控制,而不是传统的在对象内部直接控制(如new一个对象实例)。理解IOC的关键是要明确“谁控制谁?控制什么?为何是反转(有反转就应该有正转)?哪些方面反转了?

  • 谁控制谁?控制什么?
    传统Java SE程序设计,我们直接通过new进行创建对象,是主动去创建依赖对象;
    而IOC是有专门一个容器来创建这些对象,即由IOC容器来控制对象的创建。
    谁控制谁?当然是IOC控制了Bean。
    控制什么?主要控制了外部资源获取(不只是对象,包括文件等)。

  • 为何是反转?哪些方面反转了?
    有反转就有正转,传统程序是由我们主动控制去直接获取依赖对象,也就是正转。
    而反转则是由容器来帮忙创建及注入依赖对象。
    为何反转?因为由IOC帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转。
    哪些方面反转了?依赖对象的获取被反转了
    以前是主动的new对象,现在是被动的接收对象。
           Spring IOC容器学习总结_第4张图片
                         (传统应用程序示意)

传统应用程序(主动模式):

//用户类
public class User{
	private UserInfo userInfo;
	public void setUserInfo(UserInfo userInfo){
    	this.userInfo = userInfo;
	}
	public UserInfo getUserInfo(){
    	return this.userInfo;
	}
}
//用户信息类
public class UserInfo{
	private Integer userId;
	private String userName;
	public void setUserId(Integer userId){
    	this.userId = userId;
	}
	public Integer getUserId(){
    	return this.userId;
	}
	public void setUserName(String userName){
    	this.userName = userName;
	}
}
//客户端类
public class Test{
	public static void main(String[] args){
	//主动创建UserInfo对象
	UserInfo userInfo = new UserInfo();
	//主动注入属性值
	userInfo.setUserId(1);
	userInfo.setUserName(“张三”);

	//主动创建User对象
	User user = new User();
	//主动注入属性值
	user.setUserInfo(userInfo);
	}
}

       Spring IOC容器学习总结_第5张图片
       (有IOC/DI容器后程序示意)

IOC/DI容器应用程序(被动模式):

//用户类
public class User{
	private UserInfo userInfo;
	public void setUserInfo(UserInfo userInfo){
    	this.userInfo = userInfo;
	}
	public UserInfo getUserInfo(){
    	return this.userInfo;
	}
}
//用户信息类
public class UserInfo{
	private Integer userId;
	private String userName;
	public void setUserId(Integer userId){
    	this.userId = userId;
	}
	public Integer getUserId(){
    	return this.userId;
	}
	public void setUserName(String userName){
    	this.userName = userName;
	}
}

IOC容器:applicationContext.xml


<bean id=”userInfo” class=”com.alibaba.model.UserInfo”>
	
	<property name=”userId” value=”1”>property>
	<property name=”userName” value=”张三”>property>
bean>


<bean id=”user” class=”com.alibaba.model.User”>
	
	<property name=”userInfo” ref=”userInfo”>property>
bean>

单元测试

public class Test{
@Test
public void Test1(){
    ApplicationContext context = new ClassPathXmlApplicatonContext(“applicationContext.xml”);
    User user = (User)context.getBean(“user”);
    UserInfo userInfo = user.getUserInfo();
    System.out.println(userInfo.getUserId() +”    ”+ userInfo.getUserName());
}
}

1.4. 总结

  • 如何去理解控制反转?
    反转:依赖对象的获得被反转,变为由自己创建,反转为从IOC容器中获取。
    个人认为所谓控制反转就是:获得依赖对象的方式反转了。

  • 带来的好处:
    1、代码更为简洁,不需要再去new需要的对象;
    2、面向接口编程,使用类和具体类解耦,易扩展,替换实现者;
    3、方便进行AOP增强(没有IOC就无法AOP)。

  • IOC容器做什么工作?
    负责创建和管理Bean(类的实例),它是一个工厂,负责对外提供Bean实例。
    IOC容器就是工厂模式的实例,IOC容器也被称为Bean工厂。

       Spring IOC容器学习总结_第6张图片
IOC对编程最大的改变不是代码上,而是思想上,发生了“主从换位”的变化。传统程序想获得资源都要主动出击,但是IOC/DI思想中,程序就变成被动了,被动的等待IOC容器来创建并注入它所需要的资源。好莱坞法则:别找我们,我们找你。

你可能感兴趣的:(技术分享,spring,容器,java)