首先看一下J2EE提供的@Resource注解:该注解默认安照名称进行装配,名称能够通过name属性进行指定, 假设没有指定name属性,当注解写在字段上时,默认取字段名进行依照名称查找,假设注解写在setter方法上默认取属性名进行装配。
当找不到与名称匹配的bean时才依照类型进行装配。可是须要注意的是,假设name属性一旦指定。就仅仅会依照名称进行装配。
这里我们模拟@Resource注解,便于理解注解的实现原理:
1.首先在前面模拟的容器中加入注入的方法annotationInject();
XjjClassPathXMLApplicationContext.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; /** * Xjj版容器 * */ public class XjjClassPathXMLApplicationContext { private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); private Map<String, Object> sigletons = new HashMap<String, Object>(); public XjjClassPathXMLApplicationContext(String filename){ this.readXML(filename); this.instanceBeans(); this.annotationInject(); this.injectObject(); } /** * 通过注解实现注入依赖对象 */ private void annotationInject() { for(String beanName : sigletons.keySet()){ Object bean = sigletons.get(beanName); if(bean!=null){ try { PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDescriptor properdesc : ps){ Method setter = properdesc.getWriteMethod();//获取属性的setter方法 if(setter!=null && setter.isAnnotationPresent(XjjResource.class)){ XjjResource resource = setter.getAnnotation(XjjResource.class); Object value = null; if(resource.name()!=null && !"".equals(resource.name())){ value = sigletons.get(resource.name()); }else{ value = sigletons.get(properdesc.getName()); if(value==null){ for(String key : sigletons.keySet()){ if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){ value = sigletons.get(key); break; } } } } setter.setAccessible(true); setter.invoke(bean, value);//把引用对象注入到属性 } } Field[] fields = bean.getClass().getDeclaredFields(); for(Field field : fields){ if(field.isAnnotationPresent(XjjResource.class)){ XjjResource resource = field.getAnnotation(XjjResource.class); Object value = null; if(resource.name()!=null && !"".equals(resource.name())){ value = sigletons.get(resource.name()); }else{ value = sigletons.get(field.getName()); if(value==null){ for(String key : sigletons.keySet()){ if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){ value = sigletons.get(key); break; } } } } field.setAccessible(true);//同意訪问private字段 field.set(bean, value); } } } catch (Exception e) { e.printStackTrace(); } } } } /** * 为bean对象的属性注入值 */ private void injectObject() { for(BeanDefinition beanDefinition : beanDefines){ Object bean = sigletons.get(beanDefinition.getId()); if(bean!=null){ try { PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){ for(PropertyDescriptor properdesc : ps){ if(propertyDefinition.getName().equals(properdesc.getName())){ Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private if(setter!=null){ Object value = null; if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){ value = sigletons.get(propertyDefinition.getRef()); }else{ value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType()); } setter.setAccessible(true); setter.invoke(bean, value);//把引用对象注入到属性 } break; } } } } catch (Exception e) { } } } } /** * 完毕bean的实例化 */ private void instanceBeans() { for(BeanDefinition beanDefinition : beanDefines){ try { if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim())) 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> propertys = propertysub.selectNodes(element); for(Element property : propertys){ String propertyName = property.attributeValue("name"); String propertyref = property.attributeValue("ref"); String propertyValue = property.attributeValue("value"); PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue); beanDefine.getPropertys().add(propertyDefinition); } beanDefines.add(beanDefine); } }catch(Exception e){ e.printStackTrace(); } } /** * 获取bean实例 * @param beanName * @return */ public Object getBean(String beanName){ return this.sigletons.get(beanName); } }
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 XjjResource { public String name() default ""; }BeanDefinition.java
package junit.test; import java.util.ArrayList; import java.util.List; public class BeanDefinition { private String id; private String className; private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>(); public BeanDefinition(String id, String className) { this.id = id; this.className = className; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public List<PropertyDefinition> getPropertys() { return propertys; } public void setPropertys(List<PropertyDefinition> propertys) { this.propertys = propertys; } }PropertyDefinition.java
package junit.test; public class PropertyDefinition { private String name; private String ref; private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public PropertyDefinition(String name, String ref, String value) { this.name = name; this.ref = ref; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRef() { return ref; } public void setRef(String ref) { this.ref = ref; } }PersonServiceBean.java对PersonDao进行注解方式注入
package xjj.service.impl; import junit.test.XjjResource; import xjj.dao.PersonDao; import xjj.service.PersonService; public class PersonServiceBean implements PersonService { @XjjResource private PersonDao personDao; private String name; public void setPersonDao(PersonDao personDao) { this.personDao = personDao; } public PersonServiceBean(){} public PersonServiceBean(PersonDao personDao, String name) { this.personDao = personDao; this.name = name; } public void save(){ //System.out.println(name); personDao.add(); } }
beans.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> <bean id="personDaoxxxx" class="xjj.dao.impl.PersonDaoBean"></bean> <bean id="personService" class="xjj.service.impl.PersonServiceBean"> </bean> </beans>
SpringTest2.java
package junit.test; import org.junit.BeforeClass; import org.junit.Test; import xjj.service.PersonService; public class SpringTest2 { @BeforeClass public static void setUpBeforeClass() throws Exception { } @Test public void instanceSpring(){ XjjClassPathXMLApplicationContext ctx = new XjjClassPathXMLApplicationContext("beans.xml"); PersonService personService = (PersonService)ctx.getBean("personService"); personService.save(); } }
模拟结果:成功注入了PersonDaoBean