控制反转(Inversion of Control,英文缩写为IOC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup),依赖注入应用的更加广泛一些。概念没听明白?没有关系,还是通过具体的实例来认识一下依赖注入的魅力吧。
在没有使用Spring框架之前,我们创建一个普通的javabean对象的步骤是这样的:
首先是javabean对象:
public class Bean {
private int age;
private String name;
private boolean flag;
public Bean() {
super();
}
public Bean(int age, String name) {
super();
this.age = age;
this.name = name;
}
public Bean(int age, boolean flag) {
super();
this.age = age;
this.flag = flag;
}
public Bean(int age, String name, boolean flag) {
super();
this.age = age;
this.name = name;
this.flag = flag;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public String toString() {
return "Bean [age=" + age + ", name=" + name + ", flag=" + flag + "]";
}
}
然后是创建过程:
Bean bean = new Bean(12,true,"小灯笼");
这样就得到了我们想要的bean对象实例。
在使用Spring之后,我们不仅仅可以使用普通方法创建对象,还可以通过依赖注入的方式得到我们想要的对象实例。
<bean id="beanByProperty" class="com.shi.springmvc.bean.Bean">
<property name="age" value="12">property>
<property name="name" value="李天水">property>
<property name="flag" value="false">property>
bean>
然后是获取过程:
//创建 Spring 的 IOC 容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
//从容器中获取 bean 的实例
Bean bean = (Bean) ctx.getBean("beanByProperty");
我们发现,这里不再需要new了,我们只需要创建好配置文件,在一个称为IOC的容器中抓我们想要的对象即可,传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式,其实本质上来说,这不仅是一个框架的使用,更是一种编程思想的转变。
我们在bean.xml文件中添加:
<bean id="beanByConstructor" class="com.shi.springmvc.bean.Bean">
<constructor-arg value="15">constructor-arg>
<constructor-arg value="华凤珊">constructor-arg>
<constructor-arg value="true">constructor-arg>
bean>
然后
Bean bean = (Bean) ctx.getBean("beanByConstructor");
就可以获取到我们想要的对象实例了。
我们知道一个对象可以有多个构造方法,参数个数和类型肯定也都不一样,而一个对象中可能还包含有属性对象,那么我们如何处理呢?我们继续《Spring学习笔记<四> AOP 拦截器的基本实现》的项目基础上,再添加bean.java(上面已经给出)
BeanParent.java对象
public class BeanParent {
private String country;
private String language;
private Bean bean;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public Bean getBean() {
return bean;
}
public void setBean(Bean bean) {
this.bean = bean;
}
@Override
public String toString() {
return "BeanParent [country=" + country + ", language=" + language + ", bean=" + bean + "]";
}
}
TestIOC.java文件(com.shi.springmvc.bean包下面)):
@Controller
public class TestIOC {
private String SUCCESS = "success";
//不实用Spring创建bean对象
@RequestMapping("/createBean")
private String createBean(){
Bean bean = new Bean();
bean.setAge(12);
bean.setFlag(true);
bean.setName("小灯笼");
System.out.println(bean);
return SUCCESS;
}
@RequestMapping("/getBeanByProperty")
public String getBeanByProperty(){
//创建 Spring 的 IOC 容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
//从容器中获取 bean 的实例,
//注意,这里的beanByProperty是在beans.xml中配置过的,getBean后的名字必须要和beans.xml中定义的id名称一致
//否则无法获取该HelloWorld bean的实例
Bean bean = (Bean) ctx.getBean("beanByProperty");
System.out.println(bean);
return SUCCESS;
}
@RequestMapping("/getBeanByConstructor")
public String getBeanByConstructor(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
Bean bean = (Bean) ctx.getBean("beanByConstructor");
System.out.println(bean);
return SUCCESS;
}
@RequestMapping("/getBeanByConstructor01")
public String getBeanByConstructor01(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
Bean bean = (Bean) ctx.getBean("beanByConstructor01");
System.out.println(bean);
return SUCCESS;
}
@RequestMapping("/getBeanByConstructor02")
public String getBeanByConstructor02(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
Bean bean = (Bean) ctx.getBean("beanByConstructor02");
System.out.println(bean);
return SUCCESS;
}
@RequestMapping("/getParentBeanByProperty01")
public String getParentBeanByProperty01(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
BeanParent beanParent = (BeanParent) ctx.getBean("beanParentByProp01");
System.out.println(beanParent);
return SUCCESS;
}
@RequestMapping("/getParentBeanByProperty02")
public String getParentBeanByProperty02(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/bean.xml");
BeanParent beanParent = (BeanParent) ctx.getBean("beanParentByProp02");
System.out.println(beanParent);
return SUCCESS;
}
}
test_ioc.jsp文件(WebContent文件夹下面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
"Content-Type" content="text/html; charset=UTF-8">
创建bean对象
"createBean">createBean
"getBeanByProperty">getBeanByProperty
getbeanByConstructor
"getBeanByConstructor01">getBeanByConstructor01
"getBeanByConstructor02">getBeanByConstructor02
"getParentBeanByProperty01">getParentBeanByProperty01
"getParentBeanByProperty02">getParentBeanByProperty02
bean.xml文件(src文件夹下面)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<bean id="beanByProperty" class="com.shi.springmvc.bean.Bean">
<property name="age" value="12">property>
<property name="name" value="李天水">property>
<property name="flag" value="false">property>
bean>
<bean id="beanByConstructor" class="com.shi.springmvc.bean.Bean">
<constructor-arg value="15">constructor-arg>
<constructor-arg value="华凤珊">constructor-arg>
<constructor-arg value="true">constructor-arg>
bean>
<bean id="beanByConstructor01" class="com.shi.springmvc.bean.Bean">
<constructor-arg value="15" index="0">constructor-arg>
<constructor-arg value="华凤珊" index="1" type="String">constructor-arg>
bean>
<bean id="beanByConstructor02" class="com.shi.springmvc.bean.Bean">
<constructor-arg value="15" index="0">constructor-arg>
<constructor-arg value="true" index="1" type="boolean">constructor-arg>
bean>
<bean id="beanParentByProp01" class="com.shi.springmvc.bean.BeanParent">
<property name="country" value="12">property>
<property name="language" value="李天水">property>
<property name="bean" ref="beanByProperty">property>
bean>
<bean id="beanParentByProp02" class="com.shi.springmvc.bean.BeanParent">
<property name="country" value="12">property>
<property name="language" value="李天水">property>
<property name="bean">
<bean class="com.shi.springmvc.bean.Bean">
<constructor-arg value="15">constructor-arg>
<constructor-arg value="华凤珊">constructor-arg>
<constructor-arg value="true">constructor-arg>
bean>
property>
bean>
beans>
上面的代码分别实现了:通过属性注入(getBeanByProperty),构造器注入(getBeanByConstructor),以及构造方法参数不同(getBeanByConstructor01和getBeanByConstructor02)来获取Bean对象的实例,以及对象属性中有子对象的BeanParent如何获取实例的两种方法(配置文件中使用ref和不实用ref)。
我们可以看到,我们成功获取到了Bean和BeanParent的对象实例。
最后附上demo下载地址:戳我进入