zoukankan      html  css  js  c++  java
  • Spring2.5学习3.2_编码剖析@Resource注解的实现原理

    首先看一下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);
    	}
    }

    实现注解用的类型:@XjjResource
    XjjResource.java
    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







  • 相关阅读:
    腾讯TBS加载网页无法自适应记录
    filter过滤器实现验证跳转_返回验证结果
    Oracle不连续的值,如何实现查找上一条、下一条
    springmvc.xml 中 <url-pattern></url-pattern>节点详解
    spring拦截器-过滤器的区别
    (转)spring中的拦截器(HandlerInterceptor+MethodInterceptor)
    @Value("${xxxx}")注解的配置及使用
    mybatis BindingException: Invalid bound statement (not found)
    spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)
    Spring事务管理详解_基本原理_事务管理方式
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7252595.html
Copyright © 2011-2022 走看看