本节要点:
- IOC容器概述
- IOC容器的工作原理
- BeanFactory接口及常用实现类XmlBeanFactory
- ApplicationContext接口及常用实现类
- BeanFactory和ApplicationContext的区别
1 IOC容器概述
Spring的IoC容器实现了控制反转,即在开发过程中,开发人员不需要关心容器是怎样的,也不需要调用容器的任何API。容器会自动进行被管理对象的初始化及对象之间依赖关系的维护。
在Spring中,最重要的是两个包,提供了IoC容器的基本功能
- org.springframework.beans
- org.springframework.context
2 IOC容器的工作原理
org.springframework.beans.factory.BeanFactory 是Spring 容器(也叫Spring
IoC 容器)的实际代表者,BeanFactory 是IoC 容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。整个IoC 容器就是一个大的工厂,为应用程序提供bean。
从上图可以看到,我们可以在Spring IoC 容器中配置应用程序中所需要的信息,如POJO 对象,这些对象(Bean)之间相互依赖关系,最终产出以备使用的对象。
3 BeanFactory接口及常用实现类XmlBeanFactory
BeanFactory接口提供了多个实现类来供开发人员使用,最常使用的是org.springframework.beans.factory.xml.XmlBeanFactory类,是通过XML格式的文件来配置Bean对象以维护对象之间的关系。
使用XML格式的配置文件时,配置文件的最顶层是<beans>元素,其内部包含一个或多个<bean/>元素,其中每一个<bean/>元素定义了一个bean的实例化信息以及与其他bean之间的关系 。
BeanFactory接口中的几个基本方法:
- Boolean containsBean(String name)
判断Spring容器是否包含id为name的Bean实例
- Class getType(String name)
返回容器中指定Bean实例的类型
- Object getBean(String name)
返回以给定名字注册的bean实例。根据bean的配置情况,如果为singleton模式将返回一个共享的实例,否则将返回一个新建的实例。如果没有找到指定的bean,该方法可能会抛出BeansException异常(实际上将抛出NoSuchBeanDefinitionException异常),在对bean进行实例化和预处理时也可能抛出异常
注:在实际的Web应用开发中,不需开发人员自己进行容器的初始化,生成BeanFactory对象,只需在web.xml文件中进行简单配置既可。
4 ApplicationContext接口及常用实现类
大部分时候,我们都不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器,该容器被称为Spring上下文。ApplicationContext是BeanFactory子接口,它增强了BeanFactory的功能。
ApplicationContext 接口常用的实现类:
- ClassPathXmlApplicationContext:从类路径中的XML文件载入上下文定义信息,把上下文定义文件当成类路径文件,例:
ApplicationContext context=new ClassPathXmlApplicationContext(“beans- config.xml”); - FileSystemXmlApplicationContext:从文件系统中的XML文件载入上下文信息,例:
ApplicationContext context=new FileSystemXmlApplicationContext(“d:/sp/beans-config.xml”);
区别: FileSystemXmlApplicationContext只能在指定的路径寻找文件beans-config.xml; ClassPathXmlApplicationContext可在整个类路径中寻找。 - XmlWebApplicationContext:从web系统中的XML文件载入载入上下文定义信息
5 BeanFactory和ApplicationContext的区别
ApplicationContext与BeanFactory都是Spring容器,职责都有实例化、定位、配置应用程序中的对象及建立这些对象间的依赖,但ApplicationContext提供更多功能:
- ApplicationContext继承MessageResource接口,因此提供国际化支持。
- 资源访问,比如URL和文件。
- 事件机制,可向注册为监听器的Bean发送事件。
- 载入多个配置文件。
- 以声明式的方式启动、并创建Spring容器。
6 Ioc具体实现
UserDao.java
public interface UserDao { public void getUser(); }
UserDaoMySqlImpl
public class UserDaoMySqlImpl implements UserDao{ @Override public void getUser() { System.out.println("获取mysql数据"); } }
UserDaoOracleImpl
public class UserDaoOracleImpl implements UserDao{ @Override public void getUser() { System.out.println("获取oracle数据"); } }
UserService
public interface UserService { public void getUser(); }
UserServiceImpl
public class UserServiceImpl implements UserService{ private UserDao userDao ; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); } }
Beans.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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean就是java对象,由spring容器创建和管理 --> <bean name="mysqlDao" class="com.inspur.dao.impl.UserDaoMySqlImpl"/> <bean name="oracleDao" class="com.inspur.dao.impl.UserDaoOracleImpl" /> <bean id="userService" name="userService" class="com.inspur.service.impl.UserServiceImpl" > <!-- ref引用对象(对象由spring来创建) --> <property name="userDao" ref="mysqlDao"></property> </bean> </beans>
test
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService us = (UserService)context.getBean("userService"); us.getUser(); } }
7 配置文件详解
alias[ˈeliəs] 设置别名
Bean的配置
<!-- id是bean的标识符 要唯一 如果没有配置id,name默认为标识符 如果配置id,又配置了name 那么name是别名 name可以设置多个别名 分隔符可以是空格 逗号 分号 class是bean的全类名=包名+类名 --> <bean id="userService" name="userService" class="com.inspur.service.impl.UserServiceImpl" > <!-- ref引用对象(对象由spring来创建) --> <property name="userDao" ref="mysqlDao"></property> </bean>
Import用来导入其他配置文件,实现团队协作
<import resource="entity.xml"/>
8 Ioc两种创建对象的方式(了解)
8.1通过无参的构造方法
User.java
public class User { public User() { System.out.println("user的无参构造方法");; } private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); } }
Beans.xml
<bean id="user" class="com.inspur.pojo.User"> <property name="name" value="zhangsan"></property> </bean>
8.2 通过有参构造方法来创建
User.java
public class User { public User(String name) { super(); this.name = name; System.out.println("user的有参构造方法"); } private String name; public void show(){ System.out.println("name="+name); } }
Beans.xml配置
第一种 根据参数的下标来设置
<bean id="user1" class="com.inspur.pojo.User"> <!-- index指构造方法参数下标从0开始 --> <constructor-arg index="0" value="lisi"></constructor-arg> </bean>
第二种 根据参数名称来设置
<bean id="user1" class="com.inspur.pojo.User"> <!-- name指参数名 --> <constructor-arg name="name" value="lisi"></constructor-arg> </bean>
第三种 根据参数类型来设置
<bean id="user1" class="com.inspur.pojo.User"> <!-- type指参数的类型 --> <constructor-arg type="java.lang.String" value="lisi"></constructor-arg> </bean>