Spring框架二:聊聊Spring--IOC容器的那些事儿

Spring容器是Spring框架的核心,通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。容器将创建对象,并且管理对象的整个生命周期。IOC容器更是具有依赖注入的功能,可以实例化、配置应用程序中的对象及建立这些对象建的依赖。那么问题来了,什么是IOC和依赖注入?

一、IOC:Inversion Of Control,控制反转(或DI:Dependency Inject 依赖注入)。
第一次接触这个名词感觉怪怪的,经过一段时间的学习才发现这个名词是有一定意义的。扯的有些远了,下面进入正题。
控制反转(IOC):
控制的是什么? 控制的是类的对象。
何为反转? 原来由人主动通过new实例化对象的事情,转交给Spring负责。
这样做有什么好处? 人不需要管理这些对象,解除了对象管理与人之间的耦合。

依赖注入(DI):
  控制反转,又叫依赖注入(DI)。 DI是IOC的具体实现,Spring容器通过依赖注入的方式来管理Bean之间的依赖关系。
  每个基于应用程序的java都有几个类对象,依赖注入有助于把这些类粘合在一起,同时保持他们独立。
  
下面我们来看看具体的例子,所用到的lib包:commons-logging-1.1.3.jar(日志包),junit-3.8.1.jar(测试包),spring-beans-4.1.6.RELEASE.jar、spring-context-4.1.6.RELEASE.jar、spring-core-4.1.6.RELEASE.jar、spring-expression-4.1.6.RELEASE.jar(启动Spring的四个基本包)。

1.1 建立实体类com.learn.pojo.Fruit。

package com.learn.pojo;
		public class Fruit {
			
			private String name;
		
			public String getName() {
				return name;
			}
			public void setName(String name) {
				this.name = name;
			}
			@Override
			public String toString() {
				return "Fruit [name=" + name + "]";
			}
		}

1.2 在src下创建Spring配置文件,配置文件的名称自定义,这里我使用的配置文件名称:spring.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="fruit" class="com.learn.pojo.Fruit"></bean>
	</beans>

1.3 编写测试类进行测试。

package com.learn.test;
		import org.springframework.context.ApplicationContext;
		import org.springframework.context.support.ClassPathXmlApplicationContext;
		import com.learn.pojo.Fruit;
		import junit.framework.TestCase;
		
		public class SpringTest extends TestCase {
		
			public void testSpringIoc() {
				ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
				Fruit fruit = context.getBean("fruit", Fruit.class);
				System.out.println("创建类的信息:" + fruit);
				//context.getBeanDefinitionNames(); 查询Spring的IOC容器创建的所有的类名称
				String[] names = context.getBeanDefinitionNames();
				for (String name : names) {
					System.out.println("类名称:" + name);
				}
		}
		}

1.4 结果如下:
在这里插入图片描述
小结:从该例可以清楚的看到,通过读取spring.xml配置文件里的信息,Spring的容器可以创建并管理对象。没有通过new实例化对象。这就是Spring的IOC所完成的事情,即原先由程序员主动通过new实例化对象的事情,现在转交给Spring。

二、Spring实例化对象的两种方式
2.1 通过构造器实例化对象。
默认情况下使用无参构造器创建对象,如上面的例子所示。若通过有参构造器创建对象,需要在配置文件中添加配置事例如下:
创建一Apple类。

	package com.learn.pojo;
	
	public class Apple {
	
	private String color;
	
	public Apple(String color) {
		super();
		this.color = color;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return "Apple [color=" + color + "]";
	}	
	}

将Apple类作为Fruit类的属性。

package com.learn.pojo;
	
	public class Fruit {
		
		private String name;
		
		private Apple apple;
		
		public Fruit(String name, Apple apple) {
			super();
			this.name = name;
			this.apple = apple;
		}
		public Apple getApple() {
			return apple;
		}
		public void setApple(Apple apple) {
			this.apple = apple;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		@Override
		public String toString() {
			return "Fruit [name=" + name + ", apple=" + apple + "]";
		}
	}

此时若还用1.2的配置文件会报java.lang.NoSuchMethodException的错误,原因是此时只有存在有参的构造方法,而在实体类中不存在无参构造器。配置文件如下:

	<?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">
		        <!-- 配置Apple并实例化信息 
		        		index  指定构造器参数的位置
		        		name 指定构造器参数的名称
		        		value  指定构造器参数的值
				-->
		     <bean id="apple" class="com.learn.pojo.Apple">
		     	<constructor-arg index="0" name="color" value="红色"></constructor-arg>
		     </bean>
		     <!-- 配置Fruit并实例化信息 -->
		     <bean id="fruit" class="com.learn.pojo.Fruit">
		     	<constructor-arg index="0" name="name" value="水果" type="java.lang.String"></constructor-arg>
		     	<constructor-arg index="1" ref="apple"></constructor-arg>
		     </bean>
		</beans>

测试代码与1.3的内容一致,得到结果如下:
在这里插入图片描述

小结:如上面的例子,通过构造器实例化对象,同时我们还可以这么理解依赖注入:
当一个类(Fruit)需要依赖另一个类(Apple)对象,把类Apple赋值给Fruit的过程就叫依赖注入。

2.2 通过Setter设值实例化对象。

创建实体Fruit 类:

	package com.learn.pojo;
	
	public class Fruit {
		
		private String name;
		
		private Apple apple;
		
		public Fruit() {
			super();
		}
		public Fruit(String name, Apple apple) {
			super();
			this.name = name;
			this.apple = apple;
		}
		public Apple getApple() {
			return apple;
		}
		public void setApple(Apple apple) {
			this.apple = apple;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		@Override
		public String toString() {
			return "Fruit [name=" + name + ", apple=" + apple + "]";
		}
	}

创建实体Apple 类:

	package com.learn.pojo;
	public class Apple {		
		private String color;		
		public Apple() {
			super();
		}
		public Apple(String color) {
			super();
			this.color = color;
		}
		public String getColor() {
			return color;
		}
		public void setColor(String color) {
			this.color = color;
		}
		@Override
		public String toString() {
			return "Apple [color=" + color + "]";
		}	
	}

配置文件内容如下:

<?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">
	      <!-- 配置Apple并实例化信息 -->
	     <bean id="apple" class="com.learn.pojo.Apple">
	     	<property name="color" value="青色"></property>
	     </bean>
	     <!-- 配置Fruit并实例化信息 -->
	     <bean id="fruit" class="com.learn.pojo.Fruit">
	     	<property name="name" value="水果"></property>
	     	<property name="apple" ref="apple"></property>
	     </bean>
	</beans>

运行结果:
在这里插入图片描述
注意:使用setter设值注入时,需要用到无参的构造器(需要先创建实例,再设值注入)。基于构造函数和基于 setter 方法的 DI,然而使用有强制性依存关系的构造函数和有可选依赖关系的 setter是一个比较好的做法。

小结:基于构造函数注入和基于设值函数注入中的 Spring.xml 文件的区别。唯一的区别就是在基于构造函数注入中,我 们使用的是〈bean〉标签中的〈constructor-arg〉元素,而在基于设值函数的注入中,我们使用的是〈bean〉标签中的〈property〉元素。
第二个你需要注意的点是,如果你要把一个引用传递给一个对象,那么你需要使用 标签的 ref 属性,而如果你要直接传递一个值,那么你应该使用 value 属性。

三、Spring对Bean的常用属性赋值
3.1 创建实体类

package com.xzp.spring.pojo;
	
	import java.util.List;
	import java.util.Map;
	import java.util.Set;
	
	public class Person {
		
		private int id;
		
		private String name;
		
		private Set<Integer> sets;
		
		private Map<String, String> map;
	
		public Map<String, String> getMap() {
			return map;
		}
	
		public void setMap(Map<String, String> map) {
			this.map = map;
		}
	
		public Set<Integer> getSets() {
			return sets;
		}
	
		public void setSets(Set<Integer> sets) {
			this.sets = sets;
		}
	
		public List<Integer> getLists() {
			return lists;
		}
	
		public void setLists(List<Integer> lists) {
			this.lists = lists;
		}
	
		private List<Integer> lists; 
		
		
		public Person(int id, String name) {
			super();
			this.id = id;
			this.name = name;
		}
		
		public int getId() {
			return id;
		}
	
		public void setId(int id) {
			this.id = id;
		}
	
		public String getName() {
			return name;
		}
	
		public void setName(String name) {
			this.name = name;
		}
	
		@Override
		public String toString() {
			return "Person [id=" + id + ", name=" + name + ", sets=" + sets + ", map=" + map + ", lists=" + lists + "]";
		}
	}

3.2 配置文件内容如下

<?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的各属性赋值 --> 
	       <bean id="per" class="com.xzp.spring.pojo.Person"> 
	      	<constructor-arg index="0" value="1"/>
	       		<constructor-arg index="1"  value="张三"/>
	       		<property name="sets">
	       			<set value-type="java.lang.Integer">
	       				<value>1</value>
	       				<value>2</value>
	       				<value>3</value>
	       			</set>	
	       		</property>
	       		<property name="lists">
	       			<list value-type="java.lang.Integer">
	       				<value>1</value>
	       				<value>2</value>
	       				<value>3</value>
	       			</list>
	       		</property>
	       		<property name="map">
	       			<map>
	       				<entry key="zs" value="张三"></entry>
	       				<entry key="ls" value="李四"></entry>
	       			</map>
	       		</property>
	       </bean> 
	</beans>

3.2 测试内容如下:

package com.learn.test;
	import org.springframework.context.ApplicationContext;
	import org.springframework.context.support.ClassPathXmlApplicationContext;
	import com.xzp.spring.pojo.Person;
	import junit.framework.TestCase;
	public class SpringTest extends TestCase {
		
		public void testSpring() {
			ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
			Person person = ac.getBean("per", Person.class);
			System.out.println(person);
		}
	}

3.3 输出结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值