在上一篇的基础上新增程序如下
package eleven.spring.application;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import seven.spring.application.beandefinition.BeanDefinition;
import seven.spring.application.beandefinition.PropertyBeanDefinition;
import eleven.spring.xuxlResource.XuxlResource;
public class ClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
private Map<String, Object> objsMap = new HashMap<String, Object>();
private static Logger myLogger = Logger.getLogger(ClassPathXMLApplicationContext.class);
public ClassPathXMLApplicationContext(String fileName)
throws ClassNotFoundException, IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
this.readXML(fileName);
this.instanceBeans();
this.annotationInject();
this.injectObject();
}
private void annotationInject() throws IntrospectionException,
IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
// 循环容器里的对象
for (String beanName : objsMap.keySet()) {
Object bean = objsMap.get(beanName);
if (null != bean) {
// 等到对象的成员变量的信息
PropertyDescriptor[] propertyDescriptors = Introspector
.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// 等到成员变量的set方法
Method set = propertyDescriptor.getWriteMethod();
// 判断变量的set方法是否有注释解析
if (null != set
&& set.isAnnotationPresent(XuxlResource.class)) {
// 得到注释解析对象
XuxlResource xuxlResource = set
.getAnnotation(XuxlResource.class);
String xuxlResourceName = xuxlResource.name();
Object value = null;
// 注释解析对象设置name属性
if (null != xuxlResourceName
&& !"".equals(xuxlResourceName)) {
value = objsMap.get(xuxlResourceName);
} else {
value = objsMap.get(propertyDescriptor.getName());
}
// 根据name 属性 注射不成功的话 试图根据类型注射
if (value == null) {
for (String key : objsMap.keySet()) {
if (propertyDescriptor.getPropertyType()
.isAssignableFrom(
objsMap.get(key).getClass())) {
value = objsMap.get(key);
break;
}
}
}
set.setAccessible(true);
set.invoke(bean, value);
}
}
// 没有 给成员变量的set方法 声明注释解析
// 给 成员变量 声明注释解析
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(XuxlResource.class)) {
// 得到注释解析 对象
XuxlResource xuxlResource = field
.getAnnotation(XuxlResource.class);
String xuxlResourceName = xuxlResource.name();
Object fieldValue = null;
// 注释解析对象设置name属性
if (null != xuxlResourceName
&& !"".equals(xuxlResourceName)) {
fieldValue = objsMap.get(xuxlResourceName);
} else {
fieldValue = objsMap.get(field.getName());
}
// 根据name 属性 注射不成功的话 试图根据类型注射
if (fieldValue == null) {
for (String key : objsMap.keySet()) {
if (field.getType().isAssignableFrom(
objsMap.get(key).getClass())) {
fieldValue = objsMap.get(key);
break;
}
}
}
// 字段一般是private的
field.setAccessible(true);
// 不是通过set方法
field.set(bean, fieldValue);
}
}
}
}
}
//
private void injectObject() {
for (BeanDefinition beanDefinition : beanDefinitions) {
// 将 已经实例化的对象 迭代
Object bean = objsMap.get(beanDefinition.getId());
// 要养成 对 对象判空的编码习惯
if (null != bean){
try {
// 利用自反省机制获取成员变量, 继而获得对应的get set 方法
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for (PropertyBeanDefinition myPropertyBeanDefinition : beanDefinition.getPropertys()) {
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getName().equals(myPropertyBeanDefinition.getName()) ){
// 通过调用set方法 注入
Method method = propertyDescriptor.getWriteMethod();
if (null != method) {
Object value = null;
if(myPropertyBeanDefinition.getHref() != null &&"" != myPropertyBeanDefinition.getHref().trim()){
value = objsMap.get(myPropertyBeanDefinition.getHref());
} else{
value = ConvertUtils.convert(myPropertyBeanDefinition.getValue(),propertyDescriptor.getPropertyType());
}
// 要养成 对 对象判空的编码习惯
if (value != null) {
method.setAccessible(true);
method.invoke(bean, value);
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void instanceBeans() {
myLogger.info(beanDefinitions.size());
// 利用反射 生成类
for (BeanDefinition beanDefinition : beanDefinitions) {
String className = beanDefinition.getClassName();
if (className != null && !"".equals(className.trim())) {
try {
// Class.forName(xxx.xx.xx) 返回的是一个类,
// newInstance() 后才创建一个对象
// Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类
// ,也就是说JVM会执行该类的静态代码段
myLogger.info(className);
Object object = Class.forName(className).newInstance();
objsMap.put(beanDefinition.getId(), object);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
private void readXML(String fileName) {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
document = saxReader.read(xmlPath);
Map<String, String> nsMap = new HashMap<String, String>();
// 加入命名空间
nsMap.put("ns", "http://www.springframework.org/schema/beans");
// 创建beans/bean查询路径
XPath xPath = document.createXPath("//ns:beans/ns:bean");
// 设置命名空间
xPath.setNamespaceURIs(nsMap);
// 取得根元素下的所有节点
List<Element> beans = xPath.selectNodes(document);
for (Element element : beans) {
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
myLogger.info(id);
myLogger.info(clazz);
BeanDefinition beanDefinition = new BeanDefinition(id, clazz);
// 不需要 带根路径
XPath xPathBeanDefinition = element.createXPath("ns:property");
// 设置命名空间
xPathBeanDefinition.setNamespaceURIs(nsMap);
// 取得[Element]元素下的所有 节点
List<Element> propertyBeans = xPathBeanDefinition.selectNodes(element);
for (Element propertyBean : propertyBeans) {
String name = propertyBean.attributeValue("name");
String ref = propertyBean.attributeValue("ref");
String value = propertyBean.attributeValue("value");
PropertyBeanDefinition propertyDefination = new PropertyBeanDefinition(name);
propertyDefination.setHref(ref);
propertyDefination.setValue(value);
beanDefinition.getPropertys().add(propertyDefination);
}
beanDefinitions.add(beanDefinition);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public List<BeanDefinition> getBeanDefinitions() {
return beanDefinitions;
}
public void setBeanDefinitions(List<BeanDefinition> beanDefinitions) {
this.beanDefinitions = beanDefinitions;
}
public Map<String, Object> getObjsMap() {
return objsMap;
}
public void setObjsMap(Map<String, Object> objsMap) {
this.objsMap = objsMap;
}
}
##########################################################
关于 isAssignableFrom
isAssignableFrom
public native boolean isAssignableFrom(Class cls)
-
判定 Class 对象表示的类或接口是否同参数指定的 Class 表示的类或接口相同,或是其父类或父接口。 如果成立则返回 true,否则返回 false。若该类是基类型类,且指定的类参数恰为此类则返回 true,否则返回 false。
特别地,通过标别转换或其扩展引用,此方法将测试指定的 Class 参数表示的类型能否转换为当前 Class 对象表示的类型,关于更详细信息,请参看 The Java Language Specification 的 5.1.1 和 5.1.4 节。
-
-
抛出:
NullPointerException
- 如果指定的类参数为 null。
isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。
通常调用格式是
Class1.isAssignableFrom(Class2)
调用者和参数都是 java.lang.Class 类型。
而 instanceof 是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。
格式是: oo instanceof TypeName
第一个参数是对象实例名,第二个参数是具体的类名或接口名,例如 String,InputStream。
用下面的代码进行测试,我们就可以发现他们的不同之处
/*
* Created on 2005-1-29
*/
package lang.test;
import junit.framework.TestCase;
/**
* <title> LangTest
* <description>
* <company>
* @version
* @since
*
*2005-1-29 16:19:28
*/
public class LangTest extends TestCase
{
/**
* Constructor for LangTest.
* @param name
*/
public LangTest(String name)
{
super(name);
}
public void testIsAssignedFrom1()
{
assertTrue( String.class.isAssignableFrom(Object.class));
}
public void testIsAssignedFrom2()
{
assertTrue( Object.class.isAssignableFrom(Object.class));
}
public void testIsAssignedFrom3()
{
assertTrue( Object.class.isAssignableFrom(String.class));
}
public void testInstanceOf1()
{
String ss = "";
assertTrue( ss instanceof Object);
}
public void testInstanceOf2()
{
Object o = new Object();
assertTrue( o instanceof Object);
}
}