自己创建@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);}}
- 自己创建@Resource注解
- 自己创建注解,和使用注解
- 注解 @Resource
- @Resource注解
- @Resource注解
- @Resource注解
- @Resource注解
- @Resource注解
- 注解 @Resource
- @Resource注解
- @Resource注解
- @Resource 注解
- @Resource注解
- @Resource注解
- @Resource注解
- @Resource注解
- @Resource注解
- 注解 @Resource
- c++ (virtual)虚函数
- Android架构纵横谈之——软件自愈能力 (3)
- JVM ClassLoad
- 从哈希存储到Bloom Filter
- boost学习之-Lambda
- 自己创建@Resource注解
- 关于Winnet的若干整理
- Android中ICS4.0Launcher中Fold的功能详解【androidICS4.0-->Launcher系列三】
- I2C之知(一)--I2C的简介和特性
- JS小游戏-极速快跑
- c++构造函数详解(转)
- POJ2828 思维难度较好的一道线段树
- Tomcat相关的内存设置和优化
- 两算法:求数组元素出现次数和求子数组最大和