(3) 利用 Setter方式实现 【第一种方式】 依赖注入,编码剖析Spring依赖注入的原理

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



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


  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.      
  12.     public void setPersonDao(PersonDao personDao) { 
  13.         this.personDao = personDao; 
  14.     } 
  15.  
  16.  
  17.     public void save(){ 
  18.         // 调用 依赖对象注入进来的方法了。 
  19.         personDao.add(); 
  20.     } 
  21.      


  1. package cn.itm.service; 
  2.  
  3. public interface PersonService { 
  4.  
  5.     public abstract void save(); 
  6.  

  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.            </bean> 
  13.             
  14.      
  15. </beans> 


测试类:

  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.         PersonService personService = (PersonService) ctx.getBean("personService"); 
  22.         personService.save(); 
  23.      
  24.     } 

成功。


利用setter方式的好处:可以被多个bean使用。



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


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值