IoC全称为控制反转(Inverse of Control),也叫依赖注入,是spring容器的内核,AOP、事务等都依赖于此技术。IoC说白了,就是将对象与对象之间的依赖关系从代码中转移到spring的配置文件中(默认为ApplicationContext.xml 也能够自定义名字),从而由spring进行管理。这样的好处就是下降了对象与对象之间的依赖。IoC的工做原理就是利用Java的反射功能实例化对象与对象的依赖。除此以外,IoC容器还提供了对象的实例缓存、生命周期管理、对象实例代理、事件发布、资源装载等高级功能。java
BeanFactory接口也就是你们熟知的Bean工厂,它是spring框架最核心的接口,它提供了高级的IoC配置机制,能够管理任何不一样类型的Java对象。ApplicationContext接口是继BeanFactory接口以外,另外一个重要的接口。它的功能是创建在BeanFactory接口之上的。它除了已有的功能外,还提供国际化支持和框架事件等更多面向应用的功能。对于二者的区别用最直观最简介的方式来讲就是BeanFactory是Spring框架的内核,它是给Spring用的,而ApplicationContext接口是给使用Spring框架的开发者用的。web
BeanFactory是一个类工厂,但它和通常的类工厂不一样,通常的类工厂是实例化一个类或几个类,而BeanFactory是个超级工厂,能够建立管理各类类。全部被BeanFactory管理的对象在Spring中统称为Bean.下面咱们初始化BeanFactory工厂,并在工厂中获取某个对象。spring
spring配置文件:bean.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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 给car的全部属性赋值 --> <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120"></bean> </beans>
实体类Car.javasession
public class Car { /** 品牌 */ private String brand; /** 颜色 */ private String color; /** 速率 */ private int speed; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } @Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", color='" + color + '\'' + ", speed=" + speed + '}'; } }
测试类CarTest.javaapp
public class CarTest { /** * new 方式实例化car对象 */ @Test public void newCreateCar() { Car car = new Car(); car.setBrand("捷豹xjl"); car.setColor("黑色"); car.setSpeed(200); System.out.println(car); } /** * BeanFactory 方式实例化car对象 */ @Test public void beanFactoryCreateCar() { ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); Car car = beanFactory.getBean("car", Car.class); System.out.println(car); } /** * applicationContext 方式实例化car对象 */ @Test public void applicationContextCreateCar() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml"); Car car = applicationContext.getBean("car", Car.class); System.out.println(car); } }
XmlBeanFactory经过Resource装载Spring配置信息并启动IoC容器,而后经过BeanFactory中的getBean()方法从IoC容器中获取Bean.根据Spring的内部机制,启动IoC容器时,并不会初始化配置文件中的Bean.当第一次调用getBean()时初始化。对于单例的Bean来讲,BeanFactory会缓存Bean实例,在第二次调用getBean()时,直接从IoC容器的缓存中获取Bean实例。接下来咱们经过下面的例子来证实BeanFactory的缓存机制。框架
BeanFactory的缓存测试ide
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); Car car1 = beanFactory.getBean("car", Car.class); Car car2 = beanFactory.getBean("car", Car.class); System.out.println(car1); System.out.println(car2);
上述代码咱们从IoC容器中获取了两个Car,经过输出对象的内存地址信息来判断这两个car是否为同一个测试
输出结果ui
com.xiaobai.spring.mark.Car@1d96f4b5 com.xiaobai.spring.mark.Car@1d96f4b5
经过输出结果证实了咱们以前所说的,BeanFactory的缓存机制。但在各别状况下咱们不但愿它有缓存,咱们但愿每次访问时返回的都是一个新的对象。那怎么办呢。咱们能够经过scope属性来配置。
beanx.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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 给car添加scope属性并值设置为prototype --> <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120" scope="prototype"></bean> </beans>
输出结果
com.xiaobai.spring.mark.Car@6ecf829d com.xiaobai.spring.mark.Car@79884a40
经过结果咱们看,经过给Bean设置scope="prototype"时,IoC容器每次返回的都是一个新对象了,若是想每次返回的都是同一个对象,能够设置为scope="singleton",默认不设置scope属性时scope="singleton"
Spring3.0之后支持类注解的配置方式,能够经过@Configuration注解为Spring提供配置信息,Spring为配置的注解类提供了一个专门的实现类AnnotationConfigApplicationContext,下面咱们来看一下怎么来加载配置信息
Beans.java
@Configuration public class Beans { @Bean(name = "car") public Car buildCar() { Car car = new Car(); car.setBrand("东风标志508"); car.setColor("白色"); car.setSpeed(300); return car; } }
测试用例
/** * @Configuration 方式实例化car对象 */ @Test public void configurationCreateCar() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Beans.class); Car car = applicationContext.getBean("car", Car.class); System.out.println(car); }
输出结果
Car{brand='东风标志508', color='白色', speed=300}
WebApplicationContext接口是Spring专门为Web应用准备的,它继承了ApplicationContext接口,并为Bean的scope属性增长了三个值分别是request、session、globalSession.它容许从Web根目录的路径中装载配置文件,完成初始化工做。由于它是为Web服务的,因此它必须依赖于Web容器。根据Web项目开发经验,咱们应该在web.xml配置自启动的Servlet或者Web容器监听器,来配置Web项目开发环境。Spring为这两种都提供了相应的类,来启动Spring容器。它们分别为org.springframework.web.context.ContextLoaderListener和org.springframework.web.context.ContextLoaderServlet.咱们能够根据这两种中的任何一种方式来启动WebApplicationContext。虽然两种没有什么太大的区别,均可以启动WebApplicationContext,可是只有Servlet2.3以上的版本的Web容器才支持Web容器的监听器。(包括当前版本),因此能够根据项目须要配置启动WebApplicationContext的方式。下面咱们来看一下具体的配置代码
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 下面的代码是选择Spring配置文件的路径,也能够定义Spring配置文件的名字 若是不配置Spring默认在项目根目录下查找applicationContext.xml文件 --> <context-param> <param-name>contextConfigLocation</param-name> <!-- 若是配置多个文件能够用逗号分隔,也能够用资源前缀的方式配置 ? : 匹配文件名中的一个字符 * : 匹配文件名中的任意个字符 ** : 匹配多层路径 classpath:com/t?st.xml 匹配com类路径下的com/tast.xml、tbst.xml 等 classpath:com/*.xml 匹配com类路径下的全部xml文件 classpath:com/**.xml 匹配com类路径及其子目录下的全部xml文件 --> <param-value>classpath:beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
在SpringIoC容器中一个Bean对应配置文件中的一个<bean>,id为这个Bean的名称,经过容器的getBean()方法获取对应的Bean。id在IoC容器中必须是惟一的,它的命名还要知足XML对id的命名规范:必须以字母开始,后机能够是字母、数字、连字符、下划线、等。可是,在特殊状况下,咱们须要特别的名字,那id就不容许了。这时咱们能够用name属性。name属性没有字符限制,几乎可使用任何字符,并能够设置多个名字。以下所示
<bean name="#1, $2" class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120"/>
Spring配置文件虽然不容许出现两个id的<bean>,但却能够出现两个name的<bean> 若是有多个name相同的<bean> 获取时,将返回最后声明的那个Bean,缘由是后面的<bean>覆盖了前面的<bean>.若是id和name两个属性都未指定,Spring自动将class作为Bean的名称。以下所示
<bean class="com.xiaobai.spring.mark.Car" p:brand="众泰T600S" p:color="白色" p:speed="120"/>
@Test public void applicationContextCreateCar() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml"); Car car = applicationContext.getBean("com.xiaobai.spring.mark.Car", Car.class); System.out.println(car); }
执行结果
Car{brand='众泰T600S', color='白色', speed=120}