初识Spring框架实现IOC和DI(依赖注入)
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,
IoC是什么
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。
在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:
当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2-2所示:
以上就是简单的IOC的理解
那么接下来我们就来实现下我们自己的第一个Spring示例
1.1我们准备一个HelloWord类
package cn.ljy.clazz; public class HelloWord { //名称 private String name; //性别 private String sex; //年龄 private int age; //体重 private double weight; //准备构造函数 //无参构造 初始化IOC容器时需要 public HelloWord() { } //姓名 性别 年龄的构造 public HelloWord(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } //姓名 性别 体重的构造 public HelloWord(String name, String sex, double weight) { this.name = name; this.sex = sex; this.weight = weight; } public String sayHello(){ return "HelloWord"+name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "HelloWord [name=" + name + ", sex=" + sex + ", age=" + age + ", weight=" + weight + "]"; } }
1.2我们必须得准备一个applicationContext.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:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd "> <!-- 将 HelloWord 类交给Spring容器进行管理--> <!-- 通过属性的方式传入参数 --> <bean id="HelloWord" class="cn.ljy.clazz.HelloWord"> <!-- 为参数赋值 --> <property name="name" value="巴黎的雨季"></property> </bean> </beans>
这样就整理好了第一个配置文件了,然后我们进行一道测试
package cn.ljy.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.ljy.clazz.HelloWord; import cn.ljy.clazz.NewPeople; import cn.ljy.clazz.People; import cn.ljy.clazz.Person; public class MyTest { public static void main(String[] args) { //实例化Spring容器的上下文 (创建IOC容器) ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); //通过ApplicationContext的getBean()方法,根据id来获取Bean的实例 HelloWord hello = (HelloWord)context.getBean("HelloWord"); //调用HelloWord类中的方法 System.out.println("通过属性的方式给name赋值:"); String result = hello.sayHello(); System.out.println(result); }
实现结果为:
1.3以上在配置文件中使用的是setter方法依赖注入,接下来我们使用构造器的方式来实现依赖注入
applicationContext.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:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd "> <!-- 将 HelloWord 类交给Spring容器进行管理--> <!-- 通过构造器的方式传入参数 --> <bean id="AttributeByConstructor1" class="cn.ljy.clazz.HelloWord"> <!-- 通过构造器方式传参 --> <constructor-arg value="巴黎的雨季" index="0"/> <constructor-arg value="男" index="1"/> <constructor-arg value="18" type="int"/> </bean> </beans>
执行结果如图
1.4使用引用类型,引用自定义的Bean(外部Bean)
准备一个person对象
package cn.ljy.clazz; public class Person { private String name; private int age; private Car car; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; } }
applicationContext.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:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd "> <!-- 监管Car 准备三car--> <bean id="car" class="cn.ljy.clazz.Car"> <property name="brand" value="奔驰"></property> <property name="business" value="上海"></property> <property name="price" value="300000"></property> </bean> <!-- 配置person 引用Car --> <bean id="person" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <property name="car" ref="car"></property> </bean> </bean> </beans>
执行结果
1.5使用内部Bean
<!-- 内部bean --> <bean id="person2" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <!-- 注意:内部bean只能在内部使用,不能被外部所引用 --> <property name="car" > <bean class="cn.ljy.clazz.Car"> <property name="brand" value="福特"></property> <property name="business" value="北京"></property> <property name="price" value="400000"></property> </bean> </property> </bean>
执行结果与上一步基本一致
1.6配置list集合属性
People
package cn.ljy.clazz; import java.util.List; public class People { private String name; private int age; private List<Car> cars; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } @Override public String toString() { return "People [name=" + name + ", age=" + age + ", cars=" + cars + "]"; } }
<!-- list集合属性的配置 --> <bean id="people" class="cn.ljy.clazz.People"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars"> <!-- 使用list节点为集合属性赋值 --> <list> <ref bean="car"/> <ref bean="car2"/> <ref bean="car3"/> </list> </property> </bean>
执行结果
1.7使用Map集合配置属性
NewPeople
package cn.ljy.clazz; import java.util.Map; import java.util.Properties; public class NewPeople { private String name; private int age; private Map<String,Car> cars; //配置properties属性 private Properties properties; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Map<String, Car> getCars() { return cars; } public void setCars(Map<String, Car> cars) { this.cars = cars; } public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } @Override public String toString() { return "NewPeople [name=" + name + ", age=" + age + ", cars=" + cars + "]"; } }
<!--Map集合属性值的配置 --> <bean id="people2" class="cn.ljy.clazz.NewPeople"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars"> <map> <entry key="OneCar" value-ref="car"></entry> <entry key="TwoCar" value-ref="car2"></entry> <entry key="Three"> <bean class="cn.ljy.clazz.Car"> <property name="brand" value="法拉利"></property> <property name="business" value="上海"></property> <property name="price" value="4000000"></property> </bean> </entry> </map> </property> </bean>
以上就是一些基本的常用的依赖注入了,还有几个例子我会在下面的代码中贴出来,因为用的不多,所以就不做详细的讲解了
<?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:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!-- 将 HelloWord 类交给Spring容器进行管理--> <!-- 通过属性的方式传入参数 --> <bean id="HelloWord" class="cn.ljy.clazz.HelloWord"> <!-- 为参数赋值 --> <property name="name" value="巴黎的雨季"></property> </bean> <!-- 通过构造器的方式传入参数 --> <bean id="AttributeByConstructor1" class="cn.ljy.clazz.HelloWord"> <!-- 通过构造器方式传参 --> <constructor-arg value="巴黎的雨季" index="0"/> <constructor-arg value="男" index="1"/> <constructor-arg value="18" type="int"/> </bean> <!--给第二个构造器赋值 --> <bean id="AttributeByConstructor2" class="cn.ljy.clazz.HelloWord"> <!-- 通过构造器方式传参 --> <constructor-arg value="巴黎的雨季" index="0"/> <constructor-arg name="sex" value="男" /> <constructor-arg value="130" type="double"/> </bean> <!-- 监管Car 准备三car--> <bean id="car" class="cn.ljy.clazz.Car"> <property name="brand" value="奔驰"></property> <property name="business" value="上海"></property> <property name="price" value="300000"></property> </bean> <bean id="car2" class="cn.ljy.clazz.Car"> <property name="brand" value="大众"></property> <property name="business" value="广州"></property> <property name="price" value="120000"></property> </bean> <bean id="car3" class="cn.ljy.clazz.Car"> <property name="brand" value="雪佛兰"></property> <property name="business" value="深圳"></property> <property name="price" value="150000"></property> </bean> <!-- 配置person 引用Car --> <bean id="person" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <property name="car" ref="car"></property> </bean> <!-- 内部bean --> <bean id="person2" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <!-- 注意:内部bean只能在内部使用,不能被外部所引用 --> <property name="car" > <bean class="cn.ljy.clazz.Car"> <property name="brand" value="福特"></property> <property name="business" value="北京"></property> <property name="price" value="400000"></property> </bean> </property> </bean> <!-- 级联属性的使用 --> <bean id="person3" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <property name="car" ref="car"></property> <!-- 级联,改变原来的值 注意:必须是存在car对象才可以,Spring不会自动的创建car --> <property name="car.brand" value="劳斯莱斯"></property> </bean> <!-- list集合属性的配置 --> <bean id="people" class="cn.ljy.clazz.People"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars"> <!-- 使用list节点为集合属性赋值 --> <list> <ref bean="car"/> <ref bean="car2"/> <ref bean="car3"/> </list> </property> </bean> <!--Map集合属性值的配置 --> <bean id="people2" class="cn.ljy.clazz.NewPeople"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars"> <map> <entry key="OneCar" value-ref="car"></entry> <entry key="TwoCar" value-ref="car2"></entry> <entry key="Three"> <bean class="cn.ljy.clazz.Car"> <property name="brand" value="法拉利"></property> <property name="business" value="上海"></property> <property name="price" value="4000000"></property> </bean> </entry> </map> </property> </bean> <!-- 配置properties属性--> <bean id="people3" class="cn.ljy.clazz.NewPeople"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="properties"> <props> <prop key="user">root</prop> <prop key="password">123</prop> <prop key="jdbcurl">jdbc:mysql:/test</prop> <prop key="drivarClass">com.mysql.jdbc.java</prop> </props> </property> </bean> <!-- 独立出一个bean 比如说list 需要引入新的命名空间 util--> <!-- <util:list id="cars"> <ref bean="car"/> <ref bean="car2"/> <ref bean="car3"/> </util> <bean id="people4" class="cn.ljy.clazz.People"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars" ref="cars"></property> </bean> --> <!-- 自动装配 可以使用autowire属性指定自动装配的方式 byName 根据Bean的名字和当前Bean的setter风格的属性名进行自动装配,若有匹配的,则进行自动装配 ,若没有匹配的则不进行装配 byType 根据Bean的类型和当前Bean的属性的类型进行自动装配,若IOC容器中定义了多个类型匹配的Bean 则会抛出异常 --> <bean id="person4" class="cn.ljy.clazz.Person" autowire="byName"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> </bean> </beans>