描述:spring的两大核心是ioc和aop,这里我简单的实现下ioc,即控制反转。ioc的具体解释这里不做说明,首先spring的ioc解决的核心问题就是帮助我们抛去了传统的再依赖的代码调用中new的一种形式。
1 springioc最初使用的是xml的结构化配置,也就是把实体之前的依赖关系抽离出来,在xml中进行配置,然后spring帮助我们构建这层依赖关系,并把构建的这些关系以及实例放入spring的容器中,这样我们就可以通过spring的容器去拿到我们想要的对象。
2 因为jdk1.5以后就支持了注解形式,同时spring也支持注解的模式,就是已注解的形式替代xml的配置关系。其原理都是一样的。
这里我们仅仅模拟xml读取后,对bean标签中各依赖,或者属性的注入,然后去获取想要的实例bean
首先,spring中可以有多种形式来获取到spring的xml配置文件并初始化容器
1. XmlBeanFactory 工厂bean的形式获取
Resource cr = new ClassPathResource("applicationContext.xml");
BeanFactory bf=new XmlBeanFactory(cr);
UserDao userDao = (UserDao)bf.getBean("userDao");
2 ClassPathXmlApplicationContext
使用ClassPathXmlApplicationContext对象获取,必须把applicationContext.xml放置到类的加载路径【classpath路径下】中,也就是Src下面
1.ApplicationContext factory=new ClassPathXmlApplicationContext("classpath:appcontext.xml");
factory.getBean();3 FileSystemXmlApplicationContext
使用文件的系统路径,可以是本地的任何位置
4 XmlWebApplicationContext
在web项目中根据web.xml中配置的xml路径进行读取
------------------------------------------------------------
这里我们自己实现一个BeanFactory实现如下简单功能
1 读取xml
2 解析xml
3 反射获取
4 反射注入
具体代码如下
package test.spring;
import com.sun.xml.internal.bind.v2.runtime.output.NamespaceContextImpl;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class BeanFactory {
public static Map<String,Object> contain = null;
public void init(String xml) throws DocumentException, IllegalAccessException, InstantiationException, ClassNotFoundException, IntrospectionException, InvocationTargetException {
contain = new HashMap<String,Object>();
SAXReader reader = new SAXReader();
// 从class目录下获取指定的xml文件
InputStream ins = BeanFactory.class.getResourceAsStream(xml);
Document doc = reader.read(ins);
Element root = doc.getRootElement();
System.out.println(root.getName());
Element foo;
// 遍历bean
Iterator<Element> iterator = root.elementIterator("bean"); //获取所有bean标签集合
while(iterator.hasNext()){
Element bean = iterator.next();
Attribute key = bean.attribute("id");
if("".equals(key.getText())){
throw new NullPointerException();
}
Attribute clazzName = bean.attribute("class");
if("".equals(clazzName.getText())){
throw new NullPointerException();
}
Object obj = classFor(clazzName.getText());
Iterator<Element> propertys = bean.elementIterator("property");
while(propertys.hasNext()){
Element property = propertys.next();
Attribute name = property.attribute("name");
Attribute value = property.attribute("value");
if(value!=null){
setProperty(obj,name.getText(),value.getValue());
}
Attribute ref = property.attribute("ref");
if(ref != null){
Object nObj = contain.get(ref.getText());
if(nObj != null){
setProperty(obj,name.getText(),nObj);
}
}
}
contain.put(key.getText(), obj);
}
}
public <T> T getBean(String beanName){
return (T)contain.get(beanName);
}
public <T> T classFor(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class c = Class.forName(className);
T t = (T)c.newInstance();
return t;
}
/***
* 通过class的getMethod方法可以获取到指定的方法对象,
* @param clazz
* @return
* @throws IntrospectionException
*/
private BeanInfo getBeanInfo(Class clazz) throws IntrospectionException {
return Introspector.getBeanInfo(clazz);
}
private void setProperty(Object o,String propertyName,Object val) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
BeanInfo bi = getBeanInfo(o.getClass());
PropertyDescriptor[] propertyDescriptors = bi.getPropertyDescriptors();
if(propertyDescriptors != null && propertyDescriptors.length>0){
for (PropertyDescriptor pd : propertyDescriptors){
if(pd.getName().equals(propertyName)){
Object type = pd.getPropertyType(); //当前属性的类型
Method method = pd.getWriteMethod(); //获取当前属性对应的set方法
method.invoke(o,val);
break;
}
}
}
}
private Object getPropertyValByBeanInfo(Object o,String propertyName) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
BeanInfo bi = getBeanInfo(o.getClass());
PropertyDescriptor[] propertyDescriptors = bi.getPropertyDescriptors();
Object val = null;
if(propertyDescriptors != null && propertyDescriptors.length>0){
for(PropertyDescriptor pd : propertyDescriptors){
if(pd.getName().equals(propertyName)){
Method method = pd.getReadMethod();
val = method.invoke(o,propertyName);
break;
}
}
}
return val;
}
}
上面的代码仅仅是简单的实现,并没有考虑复杂的情况,也仅仅是做个原理性了解