(4) 编码剖析Spring装配基本属性的原理【附加:注入依赖对象的两种方式】

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  5.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 
  6.             
  7.            <bean id="personDao" class="cn.itm.dao.impl.PersonDaoBean"></bean> 
  8.             
  9.            <bean id="personService" class="cn.itm.service.impl.PersonServiceBean" > 
  10.                 <!--  实现 注入 --> 
  11.                 <property name="personDao" ref="personDao"></property> 
  12.                  
  13.                 <span style="color:#CC0000;"><strong><property name="name" value="itm"></property> 
  14.                 <property name="id" value="88"></property></strong></span> 
  15.            </bean> 
  16.             
  17.      
  18. </beans> 


下面包含:属性的name,id.

  1. package cn.itm.service.impl; 
  2.  
  3. import cn.itm.dao.PersonDao; 
  4. import cn.itm.service.PersonService; 
  5.  
  6. public class PersonServiceBean implements PersonService{ 
  7.  
  8.     // 使用 Set方法 是实现依赖注入: 
  9.     private PersonDao personDao; 
  10.      
  11.     // 注入 属性:<property name="name" value="itm"></property> 
  12.     private String name; 
  13.      
  14.     private Integer id; 
  15.      
  16.     public Integer getId() { 
  17.         return id; 
  18.     } 
  19.  
  20.  
  21.     public void setId(Integer id) { 
  22.         this.id = id; 
  23.     } 
  24.  
  25.  
  26.     public String getName() { 
  27.         return name; 
  28.     } 
  29.  
  30.  
  31.     public void setName(String name) { 
  32.         this.name = name; 
  33.     } 
  34.  
  35.  
  36.     public void setPersonDao(PersonDao personDao) { 
  37.         this.personDao = personDao; 
  38.     } 
  39.  
  40.  
  41.     public void save(){ 
  42.          
  43.         System.out.println("id = " + id + "," +name); 
  44.         // 调用 依赖对象注入进来的方法了。 
  45.         personDao.add(); 
  46.     } 
  47.      

  1. public interface PersonService { 
  2.  
  3.     public abstract void save(); 
  4.  

  1. package cn.itm.dao.impl; 
  2.  
  3. import cn.itm.dao.PersonDao; 
  4.  
  5.  
  6. public class PersonDaoBean implements PersonDao { 
  7.  
  8.      
  9.     public void add(){ 
  10.         System.out.println("执行PersonDaoBean的add方法。。。"); 
  11.     } 

  1. package cn.itm.dao; 
  2.  
  3. public interface PersonDao { 
  4.  
  5.     public abstract void add(); 
  6.  


装载基本属性的value


  1. package junit.test; 
  2.  
  3. /**
  4. * 因为 Property是 属于 bean的属性,所以也要在  bean中定义Property。
  5. *
  6. * @author Administrator
  7. *
  8. */ 
  9. public class PropertyDefinition { 
  10.  
  11.     private  String name; 
  12.     private String ref; 
  13.      
  14.     private String value; 
  15.     public String getValue() { 
  16.         return value; 
  17.     } 
  18.     public void setValue(String value) { 
  19.         this.value = value; 
  20.     } 
  21.     public String getName() { 
  22.         return name; 
  23.     } 
  24.     public void setName(String name) { 
  25.         this.name = name; 
  26.     } 
  27.     public String getRef() { 
  28.         return ref; 
  29.     } 
  30.     public void setRef(String ref) { 
  31.         this.ref = ref; 
  32.     } 
  33.     public PropertyDefinition(String name, String ref,String value) { 
  34.         this.name = name; 
  35.         this.ref = ref; 
  36.         this.value = value; 
  37.     } 
  38.      
  39.      

Spring容器  bean:

  1. package junit.test; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.List; 
  5.  
  6. public class BeanDefinition { 
  7.  
  8.     private String id; 
  9.     private String className; 
  10.      
  11.     private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>(); 
  12.      
  13.      
  14.     public List<PropertyDefinition> getPropertys() { 
  15.         return propertys; 
  16.     } 
  17.     public void setPropertys(List<PropertyDefinition> propertys) { 
  18.         this.propertys = propertys; 
  19.     } 
  20.     public String getId() { 
  21.         return id; 
  22.     } 
  23.     public void setId(String id) { 
  24.         this.id = id; 
  25.     } 
  26.     public String getClassName() { 
  27.         return className; 
  28.     } 
  29.     public void setClassName(String className) { 
  30.         this.className = className; 
  31.     } 
  32.     public BeanDefinition(String id, String className) { 
  33.         this.id = id; 
  34.         this.className = className; 
  35.     } 
  36.      
  37.      

下面是:模拟Spring容器装配基本属性的原理



代码如下:

  1. package junit.test; 
  2.  
  3.  
  4. import java.beans.Introspector; 
  5. import java.beans.PropertyDescriptor; 
  6. import java.lang.reflect.Method; 
  7. import java.net.URL; 
  8. import java.util.ArrayList; 
  9. import java.util.HashMap; 
  10. import java.util.List; 
  11. import java.util.Map; 
  12.  
  13. import org.apache.commons.beanutils.ConvertUtils; 
  14. import org.dom4j.Document; 
  15. import org.dom4j.Element; 
  16. import org.dom4j.XPath; 
  17. import org.dom4j.io.SAXReader; 
  18.  
  19. public class ItmClassPathXMLApplicationContext { 
  20.      
  21.     private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); 
  22.     // 存放实例 
  23.     private Map<String,Object> sigletons = new HashMap<String,Object>(); 
  24.      
  25.     public ItmClassPathXMLApplicationContext(String fileName){ 
  26.         this.readXML(fileName); 
  27.         this.instanceBeans(); 
  28.         this.injectObject(); 
  29.     } 
  30.  
  31.     private void injectObject() { 
  32.         for(BeanDefinition beanDefinition : beanDefines){ 
  33.             // 得到  bean 。。 
  34.             Object bean = sigletons.get(beanDefinition.getId()); 
  35.             if(bean != null){ 
  36.                 try
  37.                     // 得到 bean的属性描述: 
  38.                     PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 
  39.                     // 循环  bean里面的 所有的属性: 
  40.                     for( PropertyDefinition propertyDefinition: beanDefinition.getPropertys()){ 
  41.                         for(PropertyDescriptor propertyDesc /*这里是 bean 里面的属性*/ : ps){ 
  42.                             if(propertyDefinition.getName().equals(propertyDesc.getName())){ 
  43.                                 // 如果相等 说明是存在 于 这个bean的。。。 
  44.                                 Method setter = propertyDesc.getWriteMethod();   // 获取属性的 setter方法。 
  45.                                 // 最好做一下判断: 
  46.                                 if(setter != null){ 
  47.                                      
  48.                                     Object value = null
  49.                                     if(propertyDefinition.getRef() != null && !"".equals(propertyDefinition.getRef().trim())){ 
  50.                                         // 注入依赖对象: 
  51.                                         value = sigletons.get(propertyDefinition.getRef()); 
  52.                                     }else
  53.                                         // 注入基本类型。。。把字符串的值  传换成  属性的值。 
  54.                                         value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDesc.getPropertyType()); 
  55.                                     } 
  56.                                     setter.setAccessible(true); // 允许访问 私有的方法。。 
  57.                                     setter.invoke(bean, value);// 把引用对象注入到属性。 
  58.                                 } 
  59.                                 break
  60.                             } 
  61.                         } 
  62.                     } 
  63.                 } catch (Exception e) { 
  64.                     e.printStackTrace(); 
  65.                 } 
  66.             } 
  67.         } 
  68.     } 
  69.  
  70.     /**
  71.      * 通过反射技术,完成  bean 的实例化:
  72.      */ 
  73.     private void instanceBeans() { 
  74.         for(BeanDefinition beanDefinition : beanDefines){ 
  75.             try
  76.                 if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){ 
  77.                     sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance()); 
  78.                 } 
  79.             } catch (Exception e) { 
  80.                 e.printStackTrace(); 
  81.             } 
  82.         } 
  83.          
  84.     } 
  85.      
  86.  
  87.  
  88.     /**
  89.      * 读取  XML 的配置文件:
  90.      * @param fileName
  91.      */ 
  92.     @SuppressWarnings("unchecked"
  93.     private void readXML(String fileName) { 
  94.         // 创建读取器: 
  95.         SAXReader saxReader = new SAXReader(); 
  96.         Document document = null
  97.          
  98.         try
  99.             URL xmlPath = this.getClass().getClassLoader().getResource(fileName); 
  100.             document = saxReader.read(xmlPath); // 读取文件的内容。。。 
  101.              
  102.             Map<String,String> nsMap = new HashMap<String,String>(); 
  103.             nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空间 
  104.              
  105.             // 创建beans/bean 查询路径。 
  106.             XPath xsub = document.createXPath("//ns:beans/ns:bean");   
  107.              
  108.             // 设置命名空间。 
  109.             xsub.setNamespaceURIs(nsMap);                                  
  110.              
  111.             // 获取文档下 所有bean节点: 
  112.             List<Element> beans = xsub.selectNodes(document); 
  113.             for(Element element : beans){ 
  114.                 String id = element.attributeValue("id");             // 获取id属性值。 
  115.                 String clazz = element.attributeValue("class");       //  获取  class 属性值。 
  116.                 BeanDefinition beanDefine = new BeanDefinition(id, clazz); 
  117.                  
  118.                 // 查询的相对路径: 
  119.                 XPath propertysub = element.createXPath("ns:property"); 
  120.                 propertysub.setNamespaceURIs(nsMap);// 设置命名空间。 
  121.                  
  122.                 List<Element> propertys = propertysub.selectNodes(element); 
  123.                 for(Element property : propertys){ 
  124.                     String propertyName = property.attributeValue("name"); 
  125.                     String propertyRef = property.attributeValue("ref"); 
  126.                      
  127.                     String propertyValue = property.attributeValue("value"); 
  128.                      
  129.                     System.out.println(propertyName + "==" + propertyRef); 
  130.                     PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyRef, propertyValue); 
  131.                      
  132.                     // 放到  bean里面去: 
  133.                     beanDefine.getPropertys().add(propertyDefinition); 
  134.                      
  135.                 } 
  136.                 beanDefines.add(beanDefine); 
  137.             } 
  138.              
  139.         }catch(Exception e){ 
  140.             e.printStackTrace(); 
  141.         } 
  142.     } 
  143.  
  144.      
  145.     /**
  146.      * 获取  bean实例
  147.      * @param beanName
  148.      * @return
  149.      */ 
  150.     public Object getBean(String beanName){ 
  151.         return this.sigletons.get(beanName); 
  152.     } 
  153.      

测试类:

  1. package junit.test; 
  2.  
  3.  
  4. import org.junit.BeforeClass; 
  5. import org.junit.Test; 
  6. import org.springframework.context.ApplicationContext; 
  7. import org.springframework.context.support.ClassPathXmlApplicationContext; 
  8.  
  9. import cn.itm.service.PersonService; 
  10.  
  11. public class SpringTest { 
  12.  
  13.     @BeforeClass 
  14.     public static void setUpBeforeClass() throws Exception { 
  15.     } 
  16.  
  17.     // 专门用来实例化  Spring 容器的。 
  18.     @Test public void instanceSpring(){ 
  19.          
  20. //      ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 
  21.         ItmClassPathXMLApplicationContext ctx = new ItmClassPathXMLApplicationContext("beans.xml"); 
  22.         PersonService personService = (PersonService) ctx.getBean("personService"); 
  23.         personService.save(); 
  24.      
  25.     } 

ok,没有问题。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值