自己创建@Resource注解

      我们可以使用@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赋值给value
								value = sigletons.get(resource.name());
							}else{
								//如果没有name值,则根据属性名到bean集合里面去取,比如
								//属性名称为 age,则查找key为age的bean实例
								value = sigletons.get(properdesc.getName());
								//如果还是没有查找到,则查找和属性相同类型的bean
								if(value==null){
									//遍历bean集合
									for(String key : sigletons.keySet()){
										//判断bean集合中的对象是否和该属性相同类型(包括父类,
										 //接口,抽象类),我们可以调用isAssignableFrom方法
										 //如果有相同类型的,则赋值给value
										if(properdesc.getPropertyType().
											isAssignableFrom(sigletons.get(key).getClass())){
											value = sigletons.get(key);
											break;
										}
									}
								}								
							}
							//设置set方法为可访问的,类似于public
							setter.setAccessible(true);
							setter.invoke(bean, value);//把引用对象注入到属性
						}
					}
					//获得bean实例声明的所有字段
					Field[] fields = bean.getClass().getDeclaredFields();
					//遍历所有的字段
					for(Field field : fields){
						//如果字段上面有注解@ItcastResource
						if(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());
							    //如果还是没有查找到,则查找和属性相同类型的bean
								if(value==null){
								    //判断bean集合中的对象是否和该属性相同类型(包括父类,
								    //接口,抽象类),我们可以调用isAssignableFrom方法
								    //如果有相同类型的,则赋值给value
									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);
	}
}

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值