自己创建@Resource注解
2012-07-15 15:27
411 查看
我们可以使用@Resource注解,为字段注入值,如果setXXX方法上有注解@Resource,那么spring容器会帮我们调用该set方法。那么注解功能是如何实现的呢?
我们先来分析 @Resource注解作用于set函数上的。
为了实现 @Resource注解的功能,我们可以根据以下几步做到:
1: 取得bean的属性描述集合
2:遍历属性集合,获取属性的set方法。
4:如果不为空,且有注解 @Resource,这时候我们就可以判断注解后面是否有相应的name属性,@Resource(name=""),如果有name属性,那么我们就到bean实例的集合中取出对应的值。
5:如果没有指定name属性,那么我们就根据属性的名称去获取,例如String age;那么我们就查找key为age的bean实例。
6:如果还是没有查找到,那么我们就到bean的集合中查找是否有和该属性一样类型的bean实例(相同类型包括父类,抽象类,接口),如果有则取出。
我们可以使用isAssignableForm方法判断是否为相同类型
7:调用setXXX方法,将我们找出的值注入到属性中去。
如果@Resource是作用于字段上面的话,判断过程和作用于set方法上面差不多。
下面是模拟@Resource的代码。
首先我们创建一个自己的注解,ItcastResource
@Target指明该注解可以作用于哪里,ElementType.FIELD, ElementType.METHOD
表明作用于字段和方法。
我们先来分析 @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); } }
相关文章推荐
- 自己创建注解,和使用注解
- [Javascript_库编写]创建自己的“JavaScript库”
- ADS创建自己的Project模板
- GitHub之创建自己的新repo
- cuda 自己创建工程,复制sdk中的代码,执行遇到的问题
- Ubuntu 下创建自己的区域截图快捷键
- ios中创建自己的框架
- ADT 下编译cocos2dx项目自己创建的项目报extra qualification错误
- 让自己创建的功能包在ROS找到
- Spring中@Autowired注解、@Resource注解的区别
- Spring注解@Resource和@Autowire的区别
- 创建您自己的浏览器扩展,第一部分: 将您的触角延伸至Chrome
- 用XMPP协议来创建自己的即时聊天app
- Spring 注解 javax.annotation.Resource和@Autowired
- 如何创建您自己的I爱纽约T恤
- Spring学习(11)---JSR-250标准注解之 @Resource、@PostConstruct、@PreDestroy
- 【Composer】如何创建并发布一个自己的包
- 自己记一点springMVC的注解
- 创建一个自己的jar包
- 创建自己的博客come on!