`

使用反射和注解模拟Spring的依赖注入

阅读更多

作为一个应用Java的反射和注解的一个使用。

首简写一个XML的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
	<bean id="studao" class="di.dao.imple.StudentDaoImple"></bean>
	<bean id="stuService"
		class="di.service.imple.StudentServiceImple">
		<property name="stuDao" ref="studao"></property>
		<property name="stuName" value="xiaobojava"></property>
		<property name="stuAge" value="23"></property>
	</bean>
</beans>

 基于上面的XML内容设计两个对象(get,set方法省略了):

/**
 * Bean的属性定义
 * 
 * @author 张明学
 */
public class PropertyDefinition {
	private String name;

	private String ref;

	private String value;
}

 

/**
 * Bean定义
 * 
 * @author 张明学
 */
public class BeanDefinition {
	private String id;

	private String className;

	private List<PropertyDefinition> propertys = null;
}

 

编写一个读取上面XML内容的工具类如下:

/**
 * 读取Spring配置文件XML的工具类
 * 
 * @author 张明学
 * 
 * 2010-6-1
 */
public class ReadXMLUtil {

	public static List<BeanDefinition> readXMLBeanDefintion(String fileName) {
		List<BeanDefinition> beanDefintionList = new ArrayList<BeanDefinition>();

		SAXReader saxReader = new SAXReader();
		Document document = null;
		try {
			// 加载配置文件
			URL xmlPath = ReadXMLUtil.class.getClassLoader().getResource(fileName);
			document = saxReader.read(xmlPath);
			// 设置一个命名空间
			Map<String, String> nameSpaceMap = new HashMap<String, String>();
			nameSpaceMap.put("ns","http://www.springframework.org/schema/beans");
			// 创建查询Bean路径
			XPath xsub = document.createXPath("//ns:beans/ns:bean");
			xsub.setNamespaceURIs(nameSpaceMap);
			List<Element> beans = xsub.selectNodes(document);
			BeanDefinition bd = null;
			XPath propertyPath = null;
			List<Element> propertys = null;
			PropertyDefinition property = null;
			
			for (Element element : beans) {
				String id = element.attributeValue("id");
				if (id == null) {
					id = element.attributeValue("name");
				}
				String name = element.attributeValue("class");
				bd = new BeanDefinition(id, name);
				// 查找属性信息
				propertyPath = element.createXPath("//ns:property");
				propertyPath.setNamespaceURIs(nameSpaceMap);
				propertys = propertyPath.selectNodes(document);
				// Bean的属性对象集合
				List<PropertyDefinition> propertyList = new ArrayList<PropertyDefinition>();
				for (Element proElement : propertys) {
					String proName = proElement.attributeValue("name");
					String proRef = proElement.attributeValue("ref");
					if(null != proRef && !"".equals(proRef)){
						property = new PropertyDefinition(proName,proRef);
					}else{
						String proValue = proElement.attributeValue("value");
						property = new PropertyDefinition();
						property.setName(proName);
						property.setValue(proValue);
					}
					propertyList.add(property);
				}
				bd.setPropertys(propertyList);
				beanDefintionList.add(bd);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return beanDefintionList;
	}

}

 

构造一个Bean工厂如下:

public class ClassPathXMLApplicationContext {

	private List<BeanDefinition> beanDefintionList = null;

	private Map<String, Object> sigletons = new HashMap<String, Object>();

	public ClassPathXMLApplicationContext(String configFileName) {
		beanDefintionList = ReadXMLUtil.readXMLBeanDefintion(configFileName);
		this.instanceBeans();
		this.injectObject();
		this.annotationInject();
	}

	/**
	 * 用于注解形式的注入
	 * 
	 */
	private void annotationInject() {
		for (String beanName : sigletons.keySet()) {
			Object bean = getBean(beanName);
			if (null != bean) {
				try {
					// 获取所有的属性
					PropertyDescriptor pd[] = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					for (PropertyDescriptor descriptor : pd) {
						// 获取set方法
						Method setter = descriptor.getWriteMethod();
						// 若在set方法设置了MyResource注解
						if(null != setter && setter.isAnnotationPresent(MyResource.class)){
							MyResource myResource = setter.getAnnotation(MyResource.class);
							String diName = null;
							Object diObject = null;
							// 设置了name属性值
							if(null != myResource.name() && !"".equals(myResource.name())){
								diName = myResource.name();
							}else{//按默认的属性值装配置
								diName = descriptor.getName();
							}
							diObject = getBean(diName);
							setter.setAccessible(true);
							setter.invoke(bean, diObject);
						}
					}
					// 获取所有字段
					Field[] fields = bean.getClass().getDeclaredFields();
					for (Field field : fields) {
						if(field.isAnnotationPresent(MyResource.class)){
							MyResource myResource = field.getAnnotation(MyResource.class);
							String diName = null;
							Object diObject = null;
							// 设置了name属性值
							if(null != myResource.name() && !"".equals(myResource.name())){
								diName = myResource.name();
							}else{//按默认的属性值装配置
								diName = field.getName();
							}
							diObject = getBean(diName);
							field.setAccessible(true);
							field.set(bean, diObject);
						}
					}
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
	 * 基于XML配置注入Bean
	 * 
	 */
	private void injectObject() {
		for (BeanDefinition beanDefinition : beanDefintionList) {
			Object obj = getBean(beanDefinition.getId());
			if (null != obj) {
				// 属性信息
				List<PropertyDefinition> propertys = beanDefinition.getPropertys();
				if (null != propertys && propertys.size() > 0) {
					try {
						// 内省访问一个JavaBean获取所有属性信息
						PropertyDescriptor[] ps = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
						for (PropertyDescriptor descriptor : ps) {
							for (PropertyDefinition property : propertys) {
								if (descriptor.getName().equals(property.getName())) {
									// 引用型的ref
									if (null != property.getRef()&& !"".equals(property.getRef())) {
										// 获取要注入的依赖对象
										Object diObject = getBean(property.getRef());
										// 注入依赖对象
										descriptor.getWriteMethod().invoke(obj,diObject);
									} else {// value型的
										BeanUtils.setProperty(obj, property.getName(), property.getValue());
									}

								}
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	/**
	 * 实例化Bean
	 * 
	 */
	private void instanceBeans() {
		for (BeanDefinition beanDefinition : beanDefintionList) {
			try {
				Object obj = Class.forName(beanDefinition.getClassName()).newInstance();
				this.sigletons.put(beanDefinition.getId(), obj);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 获取Bean实例
	 * 
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName) {
		return this.sigletons.get(beanName);
	}

}

注解类如下:

/**
 * 自定义的一个注入的注解
 * 
 * @author 张明学
 */
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.METHOD })
public @interface MyResource {
	String name() default "";
}

 

 测试:

public interface StudentDao {
	public abstract void add();
}

 

public class StudentDaoImple implements StudentDao {
	public void add() {
		System.out.println("StudentdaoImple的add方法");
	}
}

 

public interface StudentService {
	public abstract void save();
}

 

public class StudentServiceImple implements StudentService {
	private StudentDao stuDao;
	private String stuName;
	private Integer stuAge;
	public void save() {
		System.out.println(stuName);
		System.out.println(stuAge);
		stuDao.add();
	}
	public void setStuAge(Integer stuAge) {
		this.stuAge = stuAge;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public void setStuDao(StudentDao stuDao) {
		this.stuDao = stuDao;
	}
}

 

public class StudentServiceImple2 implements StudentService {
	@MyResource
	private StudentDao stuDao;
	public void save() {
		stuDao.add();
	}
}

 

public static void main(String[] args) {
		ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext("beans2.xml");
		StudentService stuMght = (StudentService) ctx.getBean("stuService");
		stuMght.save();
	}

 

2
2
分享到:
评论
3 楼 agan112 2014-02-21  
agan112 写道

很棒!谢谢分享!
2 楼 agan112 2014-02-21  
1 楼 mayufenga1 2010-06-10  

相关推荐

Global site tag (gtag.js) - Google Analytics