Spring IOC 容器
Ioc(Inversion of control) 控制反转
“控制”就是指对 对象的创建、维护、销毁等生命周期的控制,这个过程一般是由我们的程序去主动控制的,如使用new关键字去创建一个对象(创建),在使用过程中保持引用(维护),在失去全部引用后由GC去回收对象(销毁)。
“反转”就是指将对象的创建、维护、销毁等生命周期的控制由程序控制改为由IOC容器控制,需要某个对象时就直接通过名字去IOC容器中获取。
IOC的意义何在?
IOC并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了对 对象的可靠的管理,极大地降低了开发的复杂性。
Spring 提供两种不同类型的容器:
BeanFactory容器
由org.springframework.beans.factory.BeanFactory接口定义,为依赖注入(DI)提供支持。默认采用延迟初始化策略(lazy-load)。只用当客户端对象需要访问容器中的某个收管对象的时候,才对该收管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需要的资源有限。BeanFactory容器比较适用于资源有限,且功能要求不是本严格的场景。
下面我们通过一个具体的例子,来看看BeanFactory容器的应用:
使用IDEA或Eclipse创建一个Java Project,在src下建example包,然后创建HelloWorld.java,Main.java。另外在src下创建Bean.xml用来进行bean配置。
package com.example;
public class HelloWorld {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("******" + message + "******");
}
}
package com.example;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class MainApp {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Bean.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
}
}
<?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-3.0.xsd">
<bean id="helloWorld" class="com.example.HelloWorld">
<property name="message" value="Hello World!!!"/>
</bean>
</beans>
关于Bean和xml文件,在下面详细解释。这里主要理解BeanFactory容器的用法。运行Main.java方法之后,控制台将会出现
******Hello World!!!******
ApplicationContext 容器
ApplicationContext在BeanFactory的基础上构建,由 org.springframework.context.ApplicationContext 接口定义。是相对比较高级的容器实现,除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布、国际化信息支持等。ApplicationContext所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成。所以,相对于BeanFactory来说,ApplicationContext要求更多的系统资源,同时,因为在启动时就完成所有初始化,容器启动时间较之BeanFactory也会长一些。在那些系统资源充足,并且要求更多功能的场景中,ApplicationContext类型的容器是比较合适的选择。
下面我们将上面的BeanFactory容器的例子改为用ApplicationContext容器实现。
HelloWorld.java和Bean.xml这两个不需要改动,只需要将Main.java中的实现容器改一下即可。
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
运行Main.java方法之后,控制台将会出现
******Hello World!!!******
Bean
Bean是被实例化的,组装的以及被Spring容器管理的Java对象。这些bean是由容器提供的配置元数据创建的。
bean的属性:
属性 | 描述 |
---|---|
id | Bean的唯一标识名,它必须是合法的XMLID,在整个XML文档中唯一。 |
Class | 该属性是强制性的,用来指定创建bean的bean类 |
name | 该属性用来指定唯一的bean标识符。在基于XML的配置元数组中,可以使用ID和/ 或者name属性来指定bean标识符。 |
scope | 该属性用来指定由特定的bean定义创建的对象的作用域。 |
parent | 子类Bean定义它所引用它的父类Bean。这时前面的class属性失效。子类Bean会继承父类Bean的所有属性,子类Bean也可以覆盖父类Bean的属性。注意:子类Bean和父类Bean是同一个Java类。 |
constructor-arg | 用来注入依赖关系 |
autowiring mode | 用来注入依赖关系 |
properties | 用来注入依赖关系 |
lazy-initialzation mode | 延迟初始化的bean告诉Ioc容器在它第一次被请求时,而不是在启动时去创建一个bean实例。 |
initialization | 在bean的所有必须的属性被容器设置后,调用回调方法。 |
destruction | 在包含该bean的容器被销毁时,使用回调方法。 |
Bean 的作用域
当在 Spring 中定义一个 bean 时,需要声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。
Spring 框架支持以下五个作用域,当使用 web-aware ApplicationContext 时,其中三个是可用的。
作用域 | 描述 |
---|---|
singleton | 在spring Ioc容器仅存在一个Bean实例,Bean以单例方式存在 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例 |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。仅适用于WebApplicationContext环境 |
global-session | 一般用于Portlet应用环境, 该作用域仅适用于WebApplicationContext环境 |
bean的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
指定版本号和编码方式
beans属性
<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-3.0.xsd">
...
</beans>
beans:xml文件的根节点
xmlns:XML NameSpace的缩写,因为XML文件的标签名称都是自定义的,自己写的和其他人定义的标签很有可能会重复命名,而功能却不一样,所以需要加上一个namespace来区分这个xml文件和其他的xml文件,类似于java中的package。
xmlns:xsi :是指xml文件遵守xml规范,xsi全名:xml schema instance,是指具体用到的schema资源文件里定义的元素所准守的规范。即/spring-beans-2.0.xsd这个文件里定义的元素遵守什么标准。
xsi:schemaLocation:是指,本文档里的xml元素所遵守的规范,schemaLocation 属性用来引用(schema)模式文档,解析器可以在需要时使用这个文档对 XML 实例文档进行校验。它的值(URI)是成对出现的,第一个值表示命名空间,第二个值则表示描述该命名空间的模式文档的具体位置,两个值之间以空格分隔。
bean配置:
<bean id="helloWorld" class="com.example.HelloWorld">
<property name="message" value="Hello World!!!"/>
</bean>
id为Bean的名称,可以通过容器的getBean(“helloWorld”);来获取对应的Bean
class为HelloWorld类的全限定名(包名+类名)。
加上基本的属性即可。