Spring IOC容器
IOC(控制反转)容器:
- Spring容器是Spring框架中的一个核心组件,容器将创建对象,把它们联系在一起并配置它们,管理它们的整个生命周期从创建到销毁。IOC容器是具有依赖注入功能的容器,它可以创建对象,并负责对对象进行实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。平时我们new一个新的实例,控制权在我们程序员的手里,而“控制翻转”就是指的是new的实例工作不再由程序员来做,而是交给Spring容器来做,这一节学习我们就来学习Spring的容器~
一、Spring BeanFactory容器
1、描述:
- Spring BeanFactory 容器,它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware ,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。
- 在Spring中,有大量对BeanFactory接口的实现,最常使用的是XmlBeanFactory类。该容器从XML文件中读取配置元数据,由这些元数据来生成一个被配置化的系统或者应用程序。
2、Spring BeanFactory的使用:
- 第一步:创建一个名为 SpringExample 的工程并在 src 文件夹下新建一个名为 studio_day1 的包,在与src文件同层次的文件路径中新建一个lib文件夹。
- 第二步:把Spring的所有相关jar包导入到lib文件夹中,然后右键,选择 Add External JARs 选项,导入 Spring 的库文件。
- 第三步:在studio_day1下新建名为HelloWorld的class和名为Main的class。
- 第四步:在src文件下创建Bean的配置文件Spring-conf.xml
- 第五步:开始配置Bean文件。
HelloWorld.java文件内容:
package studio_day_1;
public class HelloWorld {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayhello(){
System.out.println("hello !"+ name);
}
}
Main.java文件的内容:
package studio_day_1;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
//创建一个spring ioc容器
XmlBeanFactory context=new XmlBeanFactory(new ClassPathResource("spring-conf.xml"));
//FileSystemXmlApplicationContext 必须使用绝对地址 否则会找不到xml文件
HelloWorld helloWorld=(HelloWorld) context.getBean("helloworld");
helloWorld.sayhello();
}
}
在Main函数中,我们使用的时候需要注意:
- 第一步利用框架提供的 XmlBeanFactory() API 去生成工厂 bean 以及利用 ClassPathResource() API 去加载在路径 CLASSPATH 下可用的 bean 配置文件。XmlBeanFactory() API 负责创建并初始化所有的对象,即在配置文件中提到的 bean。
- 第二步利用第一步生成的 bean 工厂对象的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象,该对象最后可以用于实际的对象。一旦得到这个对象,你就可以利用这个对象来调用任何方法,相当于new了一个新对象,可以调用该类的所有公共函数和共有属性。
spring-conf.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 id="helloworld" class="studio_day_1.HelloWorld">
<property name="name" value="Spring!"/>
</bean>
</beans>
注意:在xml配置文件中,bean id不能重复,class必须是类的包名+类名。
如果所有配置都成功,运行结果如下:
二、Spring ApplicationContext容器
Spring ApplicationContext 容器:
- Application Context 是 BeanFactory 的子接口,也被成为 Spring 上下文。
- Application Context 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。 另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器。这个容器在 org.springframework.context.ApplicationContext interface 接口中定义。
- ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactory,ApplicationContext 会更加优秀。当然,BeanFactory 仍可以在轻量级应用中使用,比如移动设备或者基于 applet 的应用程序。
- 最常使用的ApplicationContext接口实现:
- FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
- ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
- WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
接下来我们测试Spring ApplicationContext容器:
构建过程和Spring BeanFactory容器类似,这里就不赘述。
HelloWorld.java文件内容:
package studio_day_1;
public class HelloWorld {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayhello(){
System.out.println("hello !"+ name);
}
}
Main.java文件内容:
package studio_day_1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//创建一个spring ioc容器
ApplicationContext context=new ClassPathXmlApplicationContext("spring-conf.xml");
ApplicationContext context1=
new FileSystemXmlApplicationContext("C:\\Users\\ouguangji\\Desktop\\Envs\\spring_stdio_1\\src\\spring-conf.xml");
//FileSystemXmlApplicationContext 必须使用绝对地址 否则会找不到xml文件
HelloWorld helloWorld=(HelloWorld) context.getBean("helloworld");
HelloWorld helloWorld1=(HelloWorld) context1.getBean("helloworld");
helloWorld.sayhello();
helloWorld1.sayhello();
}
}
由上可以得到使用ClassPathXmlApplicationContext,可以直接使用xml文件,不需要绝对路径就可以进行使用,但是在使用FileSystemXmlApplicationContext的时候,必须把xml文件写入绝对路径才可以正常运行。
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 id="helloworld" class="studio_day_1.HelloWorld">
<property name="name" value="Spring!"/>
</bean>
</beans>
三、Spring Bean后置处理器
Spring——Bean 后置处理器 描述:
-
Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。
-
BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。
-
你可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。
-
BeanPostProcessor 可以对 bean(或对象)实例进行操作,这意味着 Spring IoC 容器实例化一个 bean 实例,然后 BeanPostProcessor 接口进行它们的工作。
-
ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。
实现步骤如下:
步骤 | 描述 |
---|---|
1 | 创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint。 |
2 | 使用 Add External JARs 选项,添加所需的 Spring 库。 |
3 | 在 包中创建 Java 类 HelloWorld、InitHelloWorld 和 MainApp。 |
4 | 在 src 文件夹中创建 Beans 配置文件 spring-conf.xml。 |
5 | 最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。 |
这里是 HelloWorld.java 文件的内容:
package studio_day_1;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
这是InitHelloWorld.java文件内容:
- 这是实现 BeanPostProcessor 的非常简单的例子,它在任何 bean 的初始化的之前和之后输入该 bean 的名称。你可以在初始化 bean 的之前和之后实现更复杂的逻辑,因为你有两个访问内置 bean 对象的后置处理程序的方法。
package studio_day_1;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization : " + beanName);
return bean; // you can return any other object as well
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization : " + beanName);
return bean; // you can return any other object as well
}
}
这是Main.java文件内容:
package studio_day_1;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring-conf.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloworld");
obj.getMessage();
context.registerShutdownHook();
}
}
这是spring-conf.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 id="helloworld" class="studio_day_1.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
<bean class="studio_day_1.InitHelloWorld"/>
</beans>
配置完毕运行结果如下:
根据这个Spring Bean后置器的机制,我们就可以很方便的在该对象创建前和创建后进行某种操作,在开发过程中能更加的灵活多变。