您的位置:首页 > 编程语言 > Java开发

简单模拟SpringIOC工作机制流程开发

2016-10-27 11:03 423 查看
  紧接上一篇文章《轻松了解Spring中的控制反转和依赖注入》讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作。再上代码之前我们先来看看几个类的设计目的。 

  BeanFactor接口:在Spring源码中的定义是:持有对一定数量的Bean的定义,同时每个Bean都被唯一标识的对象(类),需要实现这个接口。根据对Bean的定义,该工厂将会返回一个包含Bean定义的对象的独立实例(原型设计模式),或者单例共享(一个不错的单例设计模式,)范围是整个工厂的范围(也可以理解成是整个容器下),返回哪种类型的实例依赖于Bean工厂的配置:API是相同的。因为Spring2.0中扩大了依赖范围,可以根据具体应用上下问(如在Web环境中的请求和会话),BeanFactory是应用程序组件的中央注册中心和集中配置。简单的来说该接口定义了获取Bean的方法,由子类去实现。

  BeanFactory接口:是实现BeanFactory接口的抽象基类。实现获取Bean定义的方法。

  XmlContext类:继承了AbstractBeanFactory抽象类,进行Bean的注册和注册XML的读取器。

  BeanInfo类:进行存储Bean的信息。

  接下来上代码,需要注释的地方我都添加上去了,类的目录如下。

    


  类之间的结构图如下



   以下是代码

  

package ioc.factory;

/**
* Created by zzf on 2016/10/26.
*/
public interface BeanFactory {
/**
* 根据对象的ID标识获取对象实例
* @param name
* @return
*/
Obj
4000
ect getBean(String name);
}


 

package ioc.factory;

import ioc.info.BeanInfo;
import ioc.reader.SourceReader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
* Created by zzf on 2016/10/26.
*
* 最顶层的IOC实现
* 该类负责从注册器中取出注册对象
* 实现从对象描述信息转换为对象实例的过程
* 实现根据名称获取对象的方法
*
*/
public abstract class AbstractBeanFactory implements BeanFactory {
private  String filePath;
private Map<String,BeanInfo> container;
protected SourceReader reader;
public AbstractBeanFactory(String filePath){
this.filePath=filePath;
setReader(reader);
}

/**
* 由子类决定如果使用什么样的注册读取器
* 这里使用了模板方法,父类定义抽象方法,但交给子类自由去设计方法内容
* @param reader
*/
protected abstract void setReader(SourceReader reader);

//注册bean
public void registerBeans(){
this.container=this.reader.loadBeans(filePath);
}

@Override
public Object getBean(String name) {
BeanInfo beanInfo=this.container.get(name);
if(beanInfo==null){

return null;

}else {
return this.parseBean(beanInfo);
}

}

/**
* 解析生成并生成对象实例
* 主要通过反射完成
* 根据类名,加载指定类,并取得该类的Class对象
* 使用Class对象实例化该类,获取一个对象。
* 逐个设置对象字段的值,这里采用setter Method方式
*
* @param beanInfo 指定对象的描述信息
* @return
*/
protected  Object parseBean(BeanInfo beanInfo){
Class clazz;
try {
//加载Bean的实例
clazz=Class.forName(beanInfo.getType());
Object bean=clazz.newInstance();

//获取该对象下的所有方法,包括私有
Method[] methods=clazz.getDeclaredMethods();

for (String property:beanInfo.getProperties().keySet()){
String setter="set"+ firstCharToUp(property);
for(Method method:methods){
String methodName=method.getName();

if(methodName.equals(setter)){
Object value=beanInfo.getProperties().get(property);
//使用反射调用set方法
method.invoke(bean,value);
}
}
}
return bean;

} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}

private String firstCharToUp(String property) {
System.out.println(property);
char [] c=property.toCharArray();
String first=String.valueOf(c[0]).toUpperCase();
c[0]=first.charAt(0);
System.out.println(String.valueOf(c));
return String.valueOf(c);
}
}


  

package ioc.context;

import ioc.factory.AbstractBeanFactory;
import ioc.reader.SourceReader;
import ioc.reader.XMLSourceReader;

/**
* Created by zzf on 2016/10/26.
* 上下文的构造方法
* 该方法中指明注册读取器(这里采用的XML,读者可以根据兴趣去实现另外的方式如注解)
* 并在构造该方法时一次性加载注册的对象
*/
public class XMLContext extends AbstractBeanFactory{

public XMLContext(String filePath){
super(filePath);
this.setReader(new XMLSourceReader());
super.registerBeans();
}

@Override
protected void setReader(SourceReader reader) {
super.reader=reader;
}
}


 

  

package ioc.reader;

import ioc.info.BeanInfo;

import java.util.Map;

/**
* Created by zzf on 2016/10/26.
* 注册读取器接口
* 负责读取用户注册的对象
* 继承该接口的类可以实现多种读取方式,如从配置文件中读取,根据标注读取,从网络中读取等等
*/
public interface SourceReader {
Map<String,BeanInfo> loadBeans(String filePath);
}


  

package ioc.context;

import ioc.factory.AbstractBeanFactory;
import ioc.reader.SourceReader;
import ioc.reader.XMLSourceReader;

/**
* Created by zzf on 2016/10/26.
* 上下文的构造方法
* 该方法中指明注册读取器(这里采用的XML,读者可以根据兴趣去实现另外的方式如注解)
* 并在构造该方法时一次性加载注册的对象
*/
public class XMLContext extends AbstractBeanFactory{

public XMLContext(String filePath){
super(filePath);
this.setReader(new XMLSourceReader());
super.registerBeans();
}

@Override
protected void setReader(SourceReader reader) {
super.reader=reader;
}
}
package ioc.info;

import java.lang.Object;

import java.util.HashMap;
import java.util.Map;

/**
* Created by zzf on 2016/10/26.
*/
public class BeanInfo {
private String id;
private String type;
private Map<String,Object> properties=new HashMap<String,Object>();

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public Map<String, Object> getProperties() {
return properties;
}

public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
public void addProperty(String name, Object object)
{
this.properties.put(name, object);
}
}


   

package ioc.reader;

import ioc.info.BeanInfo;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* Created by zzf on 2016/10/26.
* 使用 dom
a114
4j进行Xml的读取操作
*/
public class XMLSourceReader implements SourceReader {

@Override
public Map<String, BeanInfo> loadBeans(String filePath) {
//读取指定的配置文件
SAXReader reader = new SAXReader();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

//从class目录下获取指定的xml文件
InputStream ins = classLoader.getResourceAsStream(filePath);
Document doc = null;
try {
doc = reader.read(ins);
} catch (DocumentException e) {
e.printStackTrace();
}
//获得根节点
Element root = doc.getRootElement();
Map<String,BeanInfo>beanInfoMap=new HashMap<String, BeanInfo>();
//遍历bean
for (Iterator i = root.elementIterator("bean"); i.hasNext();){
Element element = (Element) i.next();
//获取bean的属性id和class
Attribute id = element.attribute("id");
Attribute cls = element.attribute("class");
try {
//利用Java反射机制,通过class的名称获取Class对象
Class bean=Class.forName(cls.getText());
//获取对应class的信息
java.beans.BeanInfo info= Introspector.getBeanInfo(bean);
//获取其属性描述
PropertyDescriptor [] propertyDescriptors=info.getPropertyDescriptors();
Method method;
Object object=bean.newInstance();
BeanInfo beanInfo=new BeanInfo();
for(Iterator iterator=element.elementIterator("property");iterator.hasNext();){
Element foo2= (Element) iterator.next();
//获取该property的name属性
Attribute name = foo2.attribute("name");

String value = null;
//获取该property的子元素value的值
for(Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
Element node = (Element) ite1.next();
value = node.getText();
break;
}
System.out.println("name:"+name.getText()+"value"+value);
for (int j=0;j<propertyDescriptors.length;j++){
if(propertyDescriptors[j].getName().equalsIgnoreCase(name.getText())){
method=propertyDescriptors[j].getWriteMethod();
//利用Java的反射极致调用对象的某个set方法,并将值设置进去
method.invoke(object,value);
//将获取的对象属性信息存入我们自定义的BeanInfo当中
beanInfo.addProperty(name.getText(),value);
}
}

beanInfo.setId(id.getText());
beanInfo.setType(cls.getText());
beanInfoMap.put(id.getText(),beanInfo);
}
return beanInfoMap;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

return null;
}
}


 

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: