案例:
先加入dom4j的jar包。
====================
BlogClassPathXMLApplicationContext.java
====================
package junit.test;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
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.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
public class BlogClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
public BlogClassPathXMLApplicationContext(String filename){
readXML(filename);
instanceBeans();
annotationInjection();
injectObject();
}
private void annotationInjection() {
for (BeanDefinition beanDefinition : beanDefines) {
Object bean = sigletons.get(beanDefinition.getId());
if (bean != null) {
try {
BlogResource resource = null;
Object value = null;
//按属性注解
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();//得到beanDefinition对应的类的所有属性
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
Method setter = propertyDescriptor.getWriteMethod();//得到属性的settter方法
if (setter != null && setter.isAnnotationPresent(BlogResource.class)) {
resource = setter.getAnnotation(BlogResource.class);
if (resource.name() != null && !"".equals(resource.name())) {//查找顺序1:注解有name,严格按name指定的查找
value = sigletons.get(resource.name());
}else {
value = sigletons.get(propertyDescriptor.getName());//查找顺序2:注解没有name,默认按字段名称查找
if (value == null) {//查找顺序3:注解没有name,默认按字段名称查找不到,则按类型查找
for (String key : sigletons.keySet()) {
if (propertyDescriptor.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())) {
value = sigletons.get(key);
break;
}
}
}
}
setter.setAccessible(true);
setter.invoke(bean, value);
}
}
//按字段注解
Field[] fileds = bean.getClass().getDeclaredFields();
for (Field field : fileds) {
resource = field.getAnnotation(BlogResource.class);//得到字段的注解
if (resource != null) {
if (resource.name() != null && !"".equals(resource.name())) {
value = sigletons.get(resource.name());
}else {
for (String key : sigletons.keySet()) {
if (field.getType().isAssignableFrom(sigletons.get(key).getClass())) {
value = sigletons.get(key);
break;
}
}
}
field.setAccessible(true);
field.set(bean, value);
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 为属性注入值
*/
private void injectObject() {
for (BeanDefinition beanDefinition : beanDefines) {
Object bean = sigletons.get(beanDefinition.getId());
if (bean != null) {
try {
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();//得到beanDefinition对应的类的所有属性
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
for (PropertyDefiniton propertyDefiniton : beanDefinition.getProperties()) {//得到beans.xml中bean的所有property
if (propertyDescriptor.getName().equals(propertyDefiniton.getName())) {//比较beanDefinition中定义的属性与beans.xml中<bean/>节点下的property元素的name是否相同
Method setter = propertyDescriptor.getWriteMethod();
if (setter != null) {
Object arg = null;
if (propertyDefiniton.getRef() != null && !"".equals(propertyDefiniton.getRef())) {
arg = sigletons.get(propertyDefiniton.getRef());
} else {
arg = ConvertUtils.convert(propertyDefiniton.getValue(), propertyDescriptor.getPropertyType());
}
setter.setAccessible(true);
setter.invoke(bean, arg);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*for (BeanDefinition beanDefinition : beanDefines) {
try {
//得到beanDefinition对应的类的所有属性
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(Class.forName(beanDefinition.getClassName())).getPropertyDescriptors();
for ( PropertyDefiniton propertyDefiniton : beanDefinition.getProperties()) {
//得到beans.xml中bean的所有property并循环遍历
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
Method method = propertyDescriptor.getWriteMethod();
if (method != null) {
//比较beanDefinition中定义的属性与beans.xml中<bean/>节点下的property元素的name是否相同
if (propertyDescriptor.getName().equals(propertyDefiniton.getName())) {
Object arg = null;
if (propertyDefiniton.getRef() != null && !"".equals(propertyDefiniton.getRef())) {
boolean flag = false;
//将<bean/>节点下的<property/>元素与<beans/>下的所有<bean/>节点进行比较,确定<property/>所引用的<bean/>存在
for (BeanDefinition beanDefinition2 : beanDefines) {
if (beanDefinition2.getId().equals(propertyDefiniton.getRef())) {
flag = true;
arg = Class.forName(beanDefinition2.getClassName()).newInstance();
break;
}
}
if (flag == false) {
throw new Exception("property元素所引用的bean不存在!");
}
} else {
//org.apache.commons.beanutils.ConvertUtils
arg = ConvertUtils.convert(propertyDefiniton.getValue(), propertyDescriptor.getPropertyType());
}
//防止setter方法是私有的,设置成可访问的
method.setAccessible(true);
//这里不能重新实例化一个<bean/>对应的类,必须从用已经实例化并保存好的类,
//否则在外部调用时属性还是没有被注入,如果用到属性将会是null
Object object = sigletons.get(beanDefinition.getId());
method.invoke(object, arg);
break;
}
}
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}*/
}
/**
* 实例化bean对象
*/
private void instanceBeans(){
for(BeanDefinition beanDefinition : beanDefines){
if (beanDefinition.getClassName()!= null && !"".equals(beanDefinition.getClassName().trim())) {
try {
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 读取xml配置文件
* @param filename
*/
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");//加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点
for(Element element: beans){
String id = element.attributeValue("id");//获取id属性值
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
XPath propertysub = element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> properties = propertysub.selectNodes(element);//获取文档下所有property节点
for(Element property : properties){
String name = property.attributeValue("name");
String ref = property.attributeValue("ref");
String value = property.attributeValue("value");
System.out.println("name = " + name + "\tref = " + ref + "\tvalue=" + value);
PropertyDefiniton myProperty = new PropertyDefiniton(name, ref,value);
beanDefine.getProperties().add(myProperty);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return sigletons.get(beanName);
}
}
********************************************
自己开发的注解:BlogResource.java
********************************************
package junit.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface BlogResource {
public String name() default "";
}