简单模拟spring中xml方式注入
1、定义接口
package com.service;
public interface Service {
public void queryDao();
}
package com.dao;
public interface Dao {
public void query();
}
2、实现类
package com.service;
import com.dao.Dao;
public class ServiceImpl implements Service {
Dao dao ;
Dao getDao() {
return dao;
}
public void setDao(Dao dao) {
this.dao = dao;
}
public void queryDao() {
System.out.println("开始调用Dao!");
dao.query();
}
}
package com.dao;
public class DaoImpl implements Dao {
@Override
public void query(){
System.out.println("操作数据库!");
}
}
3、工厂类
package com.util;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class BeanFactory {
public Map map = new HashMap<String,Object>();
public BeanFactory(String xml) {
parseXml(xml);
}
public void parseXml(String xml){
try {
File file = new File(this.getClass().getResource("/").getPath()+"//"+xml);
SAXReader reader = new SAXReader();
Document document = reader.read(file);
Element root = document.getRootElement();
for (Iterator<Element> it1 = root.elementIterator(); it1.hasNext();) {
Element element = it1.next();
Attribute elementAttrId = element.attribute("id");
String elementId = elementAttrId.getValue();
Attribute elementAttrClass = element.attribute("class");
String elementClass = elementAttrClass.getValue();
//实例化对象
Class clazz = Class.forName(elementClass);
Object beanObject = clazz.newInstance();
map.put(elementId,beanObject);
for (Iterator<Element> it2 = element.elementIterator(); it2.hasNext();) {
Element element2 = it2.next();
if("property".equals(element2.getName())){
String attributeName = element2.attribute("name").getValue();
String attributeRef = element2.attribute("ref").getValue();
//获取目标对象中的所有属性,[规则:属性的名字一定和property中的那么保持一致]
Field field = beanObject.getClass().getDeclaredField(attributeName);
//说明依赖已经存在map中,需要将依赖注入到目标中的属性中
Object injectInObject = map.get(attributeRef);
if(map.get(attributeRef)==null){
System.out.println("依赖还没有注入,请检查以来是否在"+clazz.getName()+"对象之前已经注入!");
}
//使用反射set方法必须传的值,否则会报IllegalAccessException:"BeanFactory不能访问com.service类的成员。ServiceImpl与修饰符"
field.setAccessible(true);
field.set(beanObject,injectInObject);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getBean(String beanName){
if(map == null || map.get(beanName)==null){
return null;
}
return map.get(beanName);
}
}
4、测试类
public static void main(String args[]){
BeanFactory beanFactory = new BeanFactory("spring.xml");
System.out.println(beanFactory.map);
Service service = (ServiceImpl)beanFactory.getBean("service");
service.queryDao();
}
使用构造方式依赖注入
package com.util;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class BeanFactory {
public Map map = new HashMap<String,Object>();
public BeanFactory(String xml) {
parseXml(xml);
}
public void parseXml(String xml){
try {
File file = new File(this.getClass().getResource("/").getPath()+"//"+xml);
SAXReader reader = new SAXReader();
Document document = reader.read(file);
Element root = document.getRootElement();
for (Iterator<Element> it1 = root.elementIterator(); it1.hasNext();) {
Element element = it1.next();
Attribute elementAttrId = element.attribute("id");
String elementId = elementAttrId.getValue();
Attribute elementAttrClass = element.attribute("class");
String elementClass = elementAttrClass.getValue();
//实例化对象
Class clazz = Class.forName(elementClass);
Object beanObject = clazz.newInstance();
for (Iterator<Element> it2 = element.elementIterator(); it2.hasNext();) {
Element element2 = it2.next();
//实例化对象,如果子标签是property则默认使用setter方法,并且默认构造
String attributeName = element2.attribute("name").getValue();
String attributeRef = element2.attribute("ref").getValue();
Object injectInObject = null;
if("property".equals(element2.getName())){
injectInObject = map.get(attributeRef);
//说明依赖不存在map中,需要将依赖注入到目标中的属性中
if(injectInObject==null){
System.out.println("依赖对象还没有注册到容器!");
}
//获取目标对象中的所有属性,[规则:属性的名字一定和property中的那么保持一致]
Field field = beanObject.getClass().getDeclaredField(attributeName);
field.setAccessible(true);
field.set(beanObject,injectInObject);
//当然构造方法中可以有多个参数,这里只默认为一个注入对象
}else if("constructor-arg".equals(element2.getName())){
injectInObject = map.get(attributeRef);
if(injectInObject==null){
System.out.println("依赖对象还没有注册到容器!");
}
Constructor constructor= clazz.getConstructor(injectInObject.getClass().getInterfaces()[0]);
beanObject = constructor.newInstance(injectInObject);
}else{
System.out.println("解析中出现特殊子标签,请继续编写!");
}
}
if(beanObject==null){
beanObject = clazz.newInstance();
}
map.put(elementId,beanObject);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getBean(String beanName){
if(map == null || map.get(beanName)==null){
return null;
}
return map.get(beanName);
}
}
模拟自动装配方式,并且属性方式>自动装配,自定义异常
1、自动装配
byType方式:如果xml中beans标签中包含自动装配属性并且value=byType,我们要循环目标对象的属性,并且使用属性查找map(已注入的对象)是否一致(这里判断的是接口名字),如果一致使用set方式注入,如果map中出现两个则需要抛出自定义异常(再容器中找到两个一样的注入对象)