文档章节

浅谈Spring IOC

戴的天
 戴的天
发布于 2014/11/12 10:42
字数 924
阅读 21
收藏 0
点赞 0
评论 0

Spring的核心是IOC和AOP,今天只谈IOC,这部分内容主要集中在spring-beans包下。

容器的实现

IOC(Inversion of Control)即控制反转,也叫做依赖注入(DI),主要是实现一个容器,而该容器的功能就是进行装配、生产的工厂。同时,Spring的一个核心概念就是将所有配置信息当做bean来处理。

从而得到一个叫做BeanFactory的接口类。

package com.ddt.summer.bean.factory;

/**
 * 
 * @author daidetian@gmail.com
 */
public interface BeanFactory {
	
	/**
	 * 放入bean对象
	 * @param name
	 * @param object
	 */
	void putBean(String name, Object object);
	
	/**
	 * 根据bean名称获取bean实例
	 * @param name
	 * @return
	 */
	Object getBean(String name);

	/**
	 * 是否含有名称为name的bean
	 * @param name
	 * @return
	 */
	boolean containsBean(String name);

}

这个容器需要能进行配置的bean的读取,所以需要有一个集合类来存储这些bean,下面列出一个beanFactory的实现类

package com.ddt.summer.bean.factory;

import java.util.ArrayList;
import java.util.List;

import com.ddt.summer.bean.entity.Bean;

public class XmlBeanFactory implements BeanFactory {
	
	private List<Bean> beans = new ArrayList<Bean>();
	
	private static XmlBeanFactory factory;
	
	private XmlBeanFactory(){
	}
	
	public static XmlBeanFactory getInstance(){
		if(factory==null){
			factory = new XmlBeanFactory();
		}
		return factory;
	}
	
	@Override
	public void putBean(String name, Object object){
		Bean bean = new Bean();
		bean.setId(name);
		bean.setObject(object);
		beans.add(bean);
	}

	@Override
	public Object getBean(String name) {
		for(Bean bean:beans){
			if(bean.getId().equals(name)){
				return bean.getObject();
			}
		}
		return null;
	}

	@Override
	public boolean containsBean(String name) {
		for(Bean bean:beans){
			if(bean.getId().equals(name)){
				return true;
			}
		}
		return false;
	}
}

注意到上面的XmlBeanFactory使用了单例模式,是为了保证我们每次获取到的容器是同一个容器。

配置信息注入

有了容器后,我们就需要将配置好的信息,通过反射注入到我们实现好了的容器中。

下面举一个简单的例子,我们实现几个类。

首先实现一个大的接口类

package test;

public interface Animal {
	
	void say();

}

再来一个老鼠类

package test;

public class Mouse implements Animal{
	
	private String name;
	
	public void setName(String name){
		this.name=name;
	}
	
	public String getName(){
		return this.name;
	}
	@Override
	public void say(){
		System.out.println("mouse is "+name);
	}

}

有了老鼠,就自然会有猫类:

package test;

public class Cat implements Animal {
	
	private String name;
	private Mouse mouse;

	@Override
	public void say() {
		System.out.println("i am "+name+" !");
		System.out.println("catched:");
			mouse.say();
	}
	
	public String getName(){
		return this.name;
	}
	
	public Mouse getMouse(){
		return mouse;
	}
	
	public void setName(String name){
		this.name = name;
	}
	
	public void setMouse(Mouse mouse){
		this.mouse = mouse;
	}

}

有了这几个类,我们就可以开始我们的配置了,配置如下

<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="animal2" class="test.Mouse">
	<property name="name" value="jerry" />
</bean>
<bean id="animal" class="test.Cat">
	<property name="name" value="tom" />
	<property name="mouse" ref="animal2" />
</bean>
</beans>

最后,我们剩下的工作就是将这些配置信息注入到工厂容器里了

package simple;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import com.ddt.summer.bean.factory.BeanFactory;
import com.ddt.summer.bean.factory.XmlBeanFactory;

public class XmlReader {
	
	public static void read(){
		URL base = ClassLoader.getSystemResource("");
		File file = new File(base.getFile(),"applicationContext.xml");
		SAXBuilder builder = new SAXBuilder();
		try {
			Document doc = builder.build(file);
			Element beans = doc.getRootElement();
			paking(beans);
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void paking(Element beans){
		List<Element> list = beans.getChildren();
		for(Element beanEle:list){
			String id = beanEle.getAttributeValue("id");
			String className = beanEle.getAttributeValue("class");
			try {
				Class<?> clazz = Class.forName(className);
				Object obj = clazz.newInstance();
				BeanFactory factory = XmlBeanFactory.getInstance();
				factory.putBean(id, obj);
				List<Element> properties = beanEle.getChildren();
				for(Element property:properties){
					if("property".equals(property.getName())){
						String name = property.getAttributeValue("name");
						String value = property.getAttributeValue("value");
						if(value!=null){
							Field field = clazz.getDeclaredField(name);
							PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
							Method setterMethod = pd.getWriteMethod();
							setterMethod.invoke(obj,value);
						}
					}
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (IntrospectionException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static Object getBean(String id){
		read();
		BeanFactory factory = XmlBeanFactory.getInstance();
		return factory.getBean(id);
	}

}

这里我用Jdom来实现了对xml的读取。这样就愉快的将这些配置好的信息注入到了我们的工厂容器里了。

再来一个简单的测试

public static void main(String[] args){
		Animal a1 = (Animal) XmlReader.getBean("animal");
		a1.say();
	}

输出结果如下:

i am tom !
catched:
mouse is jerry

显然,我的如下代码基本实现了IOC的功能,由XmlBeanFactory和XmlReader来实现对具体bean的组装、生成和管理。

具体代码可以在github上找到,https://github.com/daidetian/summer

© 著作权归作者所有

共有 人打赏支持
戴的天
粉丝 16
博文 59
码字总数 79768
作品 0
杭州
技术主管
深入理解Spring源码(一)-IOC容器的定位,载入,注册

前言:Spring源码继承,嵌套层次非常多,读起来非常容易晕,小伙伴们在看文章的时候一定要跟着文章的思路自己去源码里点一点,看一看,并且多看几次。就会越来越清晰。下面开始正题 1.Spring...

Meet相识_bfa5 ⋅ 05/01 ⋅ 0

1 Spring核心:IoC容器的实现

依赖控制反转的实现有很多种方式。在Spring中,IoC容器是实现这个模式的载体, 它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方...

qq_18150351 ⋅ 04/24 ⋅ 0

Spring IoC & DI

IOC诞生的历史 在没有IoC时,关联不同模块是通过类实例实现的,代码可能是这样子的: 当YourServiceImpl的接口不变时,只需要根据业务需要更换不同的YourService实现类即可。一旦更换实现类时...

classfly ⋅ 06/18 ⋅ 0

Spring BeanFactory和FactoryBean

Spring BeanFactory和FactoryBean 1、BeanFactory BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是 Spring IOC所遵守的最底层和最基本的编程规范...

秋风醉了 ⋅ 04/16 ⋅ 0

Spring IOC知识点一网打尽!

前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 单例模式你会几种写法? 工厂模式理解了没有? 在刷Spring书籍的时候花了点时间去学习了单例模式和工...

Java3y ⋅ 05/22 ⋅ 0

SpringBoot的幕后推手...

一、背景   这两年随着微服务的盛行,SpringBoot框架水到渠成的得到了高曝光,作为程序猿的我们,现在要是不知道一点SpringBoot相关的东西,貌似出去找工作都会被深深地鄙视,不过在我们开...

Java工程师-Distance ⋅ 06/01 ⋅ 0

Spring、Spring Boot与Spring MVC

总论 Spring框架就像一个家族,有众多衍生产品例如boot、security、jpa等等。但他们的基础都是Spring的ioc和aop。ioc提供了依赖注入的容器,aop解决了面向横切面的编程;然后在此二者的基础上...

临江仙卜算子 ⋅ 05/08 ⋅ 2

阿里老司机带你使用Spring框架快速搭建Web工程项目

摘要:Spring 框架是一个开源的 Java 平台,它为容易而快速的开发出耐用的 Java 应用程序提供了全面的基础设施。借助于Spring框架可以快速搭建Web工程项目,本文中阿里巴巴高级开发工程师嵛山...

萌萌怪兽 ⋅ 05/15 ⋅ 0

Spring IoC 浅谈

谈谈对Spring IOC的理解 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的...

The_flying_pig ⋅ 2017/11/03 ⋅ 0

Spring IOC 容器源码分析系列文章导读

1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本。经过十几年的迭代,现在的 Spring 框架已经非常成熟了。Spring 包含了众多模块,包括但不限于...

coolblog ⋅ 05/30 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

解决yum安装报错Protected multilib versions

使用yum安装报错Protected multilib versions原因是因为多个库不能共存,不过更新的话也并不行,但是可以在安装命令后面加上如下一段命令: --setopt=protected_multilib=false 案例: 比如需...

北岩 ⋅ 26分钟前 ⋅ 0

为什么要学习Typescript???

简单来说 目前的typescript就是未来的javascript 为什么?? 这要从ECMA-262标准的第4版说起 对了 我们说的ES5 其实是ECMAScript3.1这个替代性建议被扶正了而已... 那么 第4版标准是什么? 看看...

hang1989 ⋅ 31分钟前 ⋅ 0

linux安装ipfs

一、下载ipfs # cd /usr/local/ipfs/ # wget https://dist.ipfs.io/go-ipfs/v0.4.15/go-ipfs_v0.4.15_linux-amd64.tar.gz # tar -zxvf go-ipfs_v0.4.15_linux-amd64.tar.gz 二、安装ipfs # ......

八戒八戒八戒 ⋅ 36分钟前 ⋅ 0

jvm程序执行慢诊断手册

生产环境最多的几种事故之一就是程序执行慢,如果是web服务的话,表现就是响应时间长。本文分享,从业多年形成的排查守则。 诊断步骤 系统资源查看 首先是系统资源查看,而且必须是在第一步。...

xpbob ⋅ 37分钟前 ⋅ 0

YII2 advanced 高级版本项目搭建-添加API应用以及多应用

一、YII安裝 安裝yii可以用composer安裝,也可以在yii中文社区下载归档文件安装 composer安装就不介绍了,因为要安装composer,比较麻烦,当然安装了composer是最好的,以后安装yii的插件要用...

botkenni ⋅ 38分钟前 ⋅ 0

在jdk1.8的环境下模拟永久代内存溢出

相信不少小伙伴在看深入理解Java虚拟机的时候,作者给我们举例一个demo来发生PermGen space 1、通过List不断添加String.intern(); 2、通过设置对应的-XX:PermSize与-XX:MaxPermSize(更快看到...

虾几把写 ⋅ 今天 ⋅ 0

开发OpenDaylight组件的完整流程

在前面介绍学习了OpenDaylight的几个重要模块后,这里再来介绍下完整开发一个模块的过程。 OSGI的bundles提供被其他OSGI组件调用的服务。这个教程中展示的是Data Packet Service去解析数据包...

wangxuwei ⋅ 今天 ⋅ 0

Java序列化和反序列化

1、什么是序列化和反序列化 序列化:把对象转换为字节序列的过程。 反序列化:把字节序列恢复成对象的过程。 2、被序列化的类需要实现serializable接口,只是为了标注该对象是可以被序列化的...

IT-Mamba ⋅ 今天 ⋅ 0

流式构建原理

流式构建需要达到分钟级的数据更新频率,Kylin采用类似于Spark Streaming的做法,每隔数分钟进行一次微构建。这边的构建需要考虑到一个延迟因素,分布式网络存在延迟等因素,该时间段的数据有...

无精疯 ⋅ 今天 ⋅ 0

在maven项目工程编写solr代码,需要的依赖

solrJ <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>6.6.2</version> </dependency> <dependency> <groupId>org.apache.httpcomponents<......

爱运动的小乌龟 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部