自己创建@Resource注解

来源:互联网 发布:苹果mac充电正常灯不亮 编辑:程序博客网 时间:2024/05/16 16:22

      我们可以使用@Resource注解,为字段注入值,如果setXXX方法上有注解@Resource,那么spring容器会帮我们调用该set方法。那么注解功能是如何实现的呢?

      我们先来分析 @Resource注解作用于set函数上的。

      为了实现 @Resource注解的功能,我们可以根据以下几步做到:

      1: 取得bean的属性描述集合

            

PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();

      2:遍历属性集合,获取属性的set方法。

          

for(PropertyDescriptor properdesc : ps){            Method setter = properdesc.getWriteMethod();//获取属性的setter方法       }
      3:判断set方法是否为空,且是否有注解 @Resource

       

        if(setter!=null && setter.isAnnotationPresent(ItcastResource.class))
             isAnnotationPresent(class c)方法用来判断是否有c类型的注解

     4:如果不为空,且有注解 @Resource,这时候我们就可以判断注解后面是否有相应的name属性,@Resource(name=""),如果有name属性,那么我们就到bean实例的集合中取出对应的值。

    5:如果没有指定name属性,那么我们就根据属性的名称去获取,例如String age;那么我们就查找key为age的bean实例。

   6:如果还是没有查找到,那么我们就到bean的集合中查找是否有和该属性一样类型的bean实例(相同类型包括父类,抽象类,接口),如果有则取出。

      我们可以使用isAssignableForm方法判断是否为相同类型

if(properdesc.getPropertyType().  isAssignableFrom(sigletons.get(key).getClass()))

   7:调用setXXX方法,将我们找出的值注入到属性中去。

   如果@Resource是作用于字段上面的话,判断过程和作用于set方法上面差不多。

   

   下面是模拟@Resource的代码。

    首先我们创建一个自己的注解,ItcastResource

     

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 ItcastResource {public String name() default "";}
  @Retention指明该注解作用的时机,RetentionPolicy.RUNTIME代表运行期。

   @Target指明该注解可以作用于哪里,ElementType.FIELD, ElementType.METHOD

表明作用于字段和方法。


    

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;}}

 

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;}}

    

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 ItcastClassPathXMLApplicationContext {private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();private Map<String, Object> sigletons = new HashMap<String, Object>();public ItcastClassPathXMLApplicationContext(String filename){this.readXML(filename);this.instanceBeans();this.annotationInject();this.injectObject();}/** * 通过注解实现注入依赖对象 */private void annotationInject() {//遍历所有的bean实例for(String beanName : sigletons.keySet()){//根据id,获得bean实例Object bean = sigletons.get(beanName);if(bean!=null){try {//取得bean的属性描述集合PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();for(PropertyDescriptor properdesc : ps){Method setter = properdesc.getWriteMethod();//获取属性的setter方法//如果set方法不为空,且setXXX()方法上面有@ItcastResource注解if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){//获取到注解对象ItcastResource resource = setter.getAnnotation(ItcastResource.class);Object value = null;//判断注解后面是否有name属性@ItcastResource(name="")if(resource.name()!=null && !"".equals(resource.name())){//如果有name值,那么将name对应的bean赋值给valuevalue = sigletons.get(resource.name());}else{//如果没有name值,则根据属性名到bean集合里面去取,比如//属性名称为 age,则查找key为age的bean实例value = sigletons.get(properdesc.getName());//如果还是没有查找到,则查找和属性相同类型的beanif(value==null){//遍历bean集合for(String key : sigletons.keySet()){//判断bean集合中的对象是否和该属性相同类型(包括父类, //接口,抽象类),我们可以调用isAssignableFrom方法 //如果有相同类型的,则赋值给valueif(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){value = sigletons.get(key);break;}}}}//设置set方法为可访问的,类似于publicsetter.setAccessible(true);setter.invoke(bean, value);//把引用对象注入到属性}}//获得bean实例声明的所有字段Field[] fields = bean.getClass().getDeclaredFields();//遍历所有的字段for(Field field : fields){//如果字段上面有注解@ItcastResourceif(field.isAnnotationPresent(ItcastResource.class)){//获取到注解对象ItcastResource resource = field.getAnnotation(ItcastResource.class);Object value = null;//判断注解后面是否有name属性@ItcastResource(name="")if(resource.name()!=null && !"".equals(resource.name())){value = sigletons.get(resource.name());}else{     //如果没有name值,则根据属性名到bean集合里面去取,比如//属性名称为 age,则查找key为age的bean实例value = sigletons.get(field.getName());    //如果还是没有查找到,则查找和属性相同类型的beanif(value==null){    //判断bean集合中的对象是否和该属性相同类型(包括父类,    //接口,抽象类),我们可以调用isAssignableFrom方法    //如果有相同类型的,则赋值给valuefor(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方法 ,privateif(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);}}