自己实现一个简单spring 注入的功能。非常简单的一个场景,在ObjectAImpl类中需要一个协作对象b
package entity;
public class ObjectAImpl implements ObjectA {
private ObjectB b;
public ObjectAImpl() {
//传统的协作类对象的创建,类之间耦合高
b = new ObjectBImpl();
}
public void setB(ObjectB b) {
this.b = b;
}
public ObjectB getB() {
return b;
}
}
xml解析用的是jdom,先定义一个工具类
package util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class Xmlutil {
public static Element XmlParse(String path) throws JDOMException, IOException {
SAXBuilder builder = new SAXBuilder();
InputStream file = new FileInputStream(path);
Document document = builder.build(file);//获得文档对象
Element root = document.getRootElement();//获得根节点
return root;
}
}
下面就是最最关键的ApplicationContext 的模拟实现了
package spring;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Element;
import org.jdom.JDOMException;
import util.Xmlutil;
import entity.ObjectAImpl;
public class ApplicationContext {
//
private Map<String,Object> beans;
ApplicationContext(String path){
beans = new HashMap<String,Object>();
Element root;
//解析xml
try {
root = Xmlutil.XmlParse(path);
//组装bean
initBeans(root);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private void initBeans(Element root) throws NoSuchMethodException {
if(!root.getName().equals("beans"))
return;
List<Element> children = root.getChildren();
for(Element temp : children){
if(!temp.getName().equals("bean"))
return;
String classname = temp.getAttribute("class").getValue();
String id = temp.getAttribute("id").getValue();
Element property = temp.getChild("property");
String propertyName ="";
String propertyValue = "";
Object bean = null;
if(property != null){
propertyName = property.getAttribute("name").getValue();
propertyValue = property.getAttribute("value").getValue();
}
try {
Class clazz = Class.forName(classname);
bean = clazz.newInstance();
//调用其setter方法
Method[] methods = clazz.getDeclaredMethods();
Method setMethod = null;
for(Method tempMethod : methods){
if(tempMethod.getName().equals("set"+ propertyName.toUpperCase())){
setMethod = tempMethod;
break;
}
}
if(setMethod != null){
Class propertyClazz = Class.forName(propertyValue);
Object propertyBean = propertyClazz.newInstance();
setMethod.invoke(bean,propertyBean);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
beans.put(id, bean);
}
}
public Object getBean(String beanId){
return beans.get(beanId);
}
public static void main(String[] args) {
ApplicationContext app = new ApplicationContext("F:/code/mySpring/resources/applicationContext.xml");
ObjectAImpl a = (ObjectAImpl)app.getBean("objectA");
a.getB().print();
}
}
定义几个测试的类
package entity;
/*
* 实现一个非常简单的功能
*
* ObjectA中需要一个objectb的对象,不直接new,而是由spring来注入
*
*
*/
public interface ObjectA {
}
package entity;
public interface ObjectB {
void print();
}
package entity;
public class ObjectAImpl implements ObjectA {
//这边只是用接口定义了一个引用,并没有实例化
private ObjectB b;
public ObjectAImpl() {
b = new ObjectBImpl();
}
public void setB(ObjectB b) {
this.b = b;
}
public ObjectB getB() {
return b;
}
}
package entity;
public class ObjectBImpl implements ObjectB {
@Override
public void print() {
System.out.println("i am b");
}
}
package entity;
public class ObjectCImpl implements ObjectB {
@Override
public void print() {
System.out.println("i am c");
}
}
新增一个配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean class="entity.ObjectAImpl" id="objectA">
<property name="b" value="entity.ObjectBImpl"/>
</bean>
</beans>
然后是测试类
package test;
import spring.ApplicationContext;
import entity.ObjectAImpl;
public class MyTest {
public static void main(String[] args) {
ApplicationContext app = new ApplicationContext("F:/code/mySpring/resources/applicationContext.xml");
ObjectAImpl a = (ObjectAImpl)app.getBean("objectA");
a.getB().print();
}
}
执行结果:
i am b
如果我们把配置文件里的b对应的类该成ObjectCImpl
<property name="b" value="entity.ObjectCImpl"/>
执行结果:
i am c
从而实现了注入