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

前端之家收集整理的这篇文章主要介绍了(3) 利用 Setter方式实现 【第一种方式】 依赖注入,编码剖析Spring依赖注入的原理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
  1. import cn.itm.dao.PersonDao;
  2. public class PersonDaoBean implements PersonDao {
  3. public void add(){
  4. System.out.println("执行PersonDaoBean的add方法。。。");
  5. }
  6. }



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


  1. package cn.itm.service.impl;
  2. import cn.itm.dao.PersonDao;
  3. import cn.itm.service.PersonService;
  4. public class PersonServiceBean implements PersonService{
  5. // 使用 Set方法 是实现依赖注入:
  6. private PersonDao personDao;
  7. public void setPersonDao(PersonDao personDao) {
  8. this.personDao = personDao;
  9. }
  10. public void save(){
  11. // 调用 依赖对象注入进来的方法了。
  12. personDao.add();
  13. }
  14. }


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

  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. <bean id="personDao" class="cn.itm.dao.impl.PersonDaoBean"></bean>
  7. <bean id="personService" class="cn.itm.service.impl.PersonServiceBean" >
  8. <!-- 实现 注入 -->
  9. <property name="personDao" ref="personDao"></property>
  10. </bean>
  11. </beans>


测试类:

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

成功。


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



下面利用编码剖析Spring依赖注入的原理:


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

猜你在找的设计模式相关文章