zoukankan      html  css  js  c++  java
  • Spring的DI(Ioc)

    注入bean有两种方式:

    注入其他bean:
    方式一
    <bean id="orderDao" class="cn.itcast.service.OrderDaoBean"/>
    <bean id="orderService" class="cn.itcast.service.OrderServiceBean">
    	<property name="orderDao" ref="orderDao"/>
    </bean>
    方式二(使用内部bean,但该bean不能被其他bean使用)
    <bean id="orderService" class="cn.itcast.service.OrderServiceBean">
    	<property name="orderDao">
    		<bean class="cn.itcast.service.OrderDaoBean"/>
    	</property>
    </bean>
    

      

    一般我们的工程在service层依赖dao层的实现来实现业务逻辑。

    service层:

    public class PersonServiceImpl implements PersonService {
    	
    	private PersonDao personDao;
    	
    	@Override
    	public void save() {
    		personDao.save();
    		System.out.println("service :  " + " save 方法");
    	}
    	public PersonDao getPersonDao() {
    		return personDao;
    	}
    	public void setPersonDao(PersonDao personDao) {
    		this.personDao = personDao;
    	}
    }
    

      

    dao层:

    public class PersonDaoImpl implements PersonDao {
    	@Override
    	public void save() {
    		System.out.println("dao层的save方法");
    	}
    }
    

      

    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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
               
        <bean id="personDaoImpl" class="cn.gbx.dao.PersonDaoImpl"></bean>
     	<bean id="personServiceImpl" class="cn.gbx.serviceimpl.PersonServiceImpl" >
     		<property name="personDao" ref="personDaoImpl"></property>
     	</bean>
    </beans>
    

      

    测试方法:

    public class SpringTest {
    	@Test
    	public void spring1() {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    		PersonService ps = (PersonService)ctx.getBean("personServiceImpl");
    		ps.save();
    	}
    }
    

      

    然后我们就实现了Spring对bean对象的依赖注入。 service层所依赖的dao层的PersonDao对象不是由service本身去创建管理,而是交给了第三方容器Spring去管理。

    那么Spring是如何管理的呢?

    我们可想而知

    1: 首先必须解析XML 将 <bean>标签和 <property>标签都解析出来

    2: 利用反射实例话对象

    3: 利用内省将实例化完成的对象注入到有依赖的对象里面

    我们可以自己模拟实现:

    package cn.gbx.myExample;
    
    import java.beans.BeanInfo;
    import java.beans.IntrospectionException;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;
    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.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.XPath;
    import org.dom4j.io.SAXReader;
    
    public class MyClassPathXmlApplicationContext {
    
    	private List<DefBean> defBeans = new ArrayList<DefBean>();  //存储<bean>标签的信息
    	private Map<String, Object> singltons = new HashMap<String, Object>(); //存储读出来的对象
    	
    	
    	public MyClassPathXmlApplicationContext() {
    		super();
    	}
    
    	public MyClassPathXmlApplicationContext(String filename) {
    		this.readXML(filename);
    		this.instanceBean();
    		this.injectProperty();
    	}
    	//利用内省将属性注入
    	private void injectProperty() {
    		for (DefBean defBean : defBeans) {
    			Object bean = singltons.get(defBean.getId());
    			if (bean != null) {
    				//要想将依赖的对象注入,我们就要通过内省来操作对象的属性
    				try {
    					BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
    					PropertyDescriptor[] ps = beanInfo.getPropertyDescriptors();
    				
    					for (DefProperty p : defBean.getDefPropertys()) {
    						for (PropertyDescriptor propertyDes : ps) {
    							if (propertyDes.getName().equals(p.getName())) {
    								Method setter = propertyDes.getWriteMethod();
    								if (setter != null) {
    									Object value = null;
    									if (p.getRef() != null && !"".equals(p.getRef())) {
    										value = singltons.get(p.getRef());
    									} else { //基本数据类型利用beanUtils实现转化
    										value = ConvertUtils.convert(p.getValue(),propertyDes.getPropertyType());
    									}
    									setter.setAccessible(true); //这样即使set方法是私有的都可以访问
    									setter.invoke(bean, value); //把引用对象注入到bean属性里面
    								}
    								break;
    							}
    						}
    					}
    				} catch (Exception e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}
    		
    	}
        //利用反射实例化对象
    	private void instanceBean() {
    		for (DefBean bean : defBeans) {
    			//输出测试读取的xml
    			/*System.out.println(bean.getId() + "  : " + bean.getClassName());
    			System.out.println("------------------------");
    			for (DefProperty p : bean.getDefPropertys()) {
    				System.out.println("Property : name = " + p.getName() + "  :  ref = " + p.getRef());
    			}
    			*/
    			
    			if (bean.getClassName() != null && !"".equals(bean.getClassName())) {
    				try {
    					singltons.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    
    	private void readXML(String filename) {
    		SAXReader reader = new SAXReader();
    		Document document = null;
    		URL xmlPath = this.getClass().getClassLoader().getResource(filename);
    		try {
    			document = reader.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");
    			xsub.setNamespaceURIs(nsMap); // 设置命名空间
    			
    			List<Element> elements = xsub.selectNodes(document);
    			
    			DefBean defBean = null;
    			for (Element e : elements) {
    				String id = e.attributeValue("id");
    				String className = e.attributeValue("class");
    				defBean = new DefBean(id, className);
    				
    				//为<bean>节点设置查询路径
    				XPath xPropertySub = e.createXPath("ns:property");
    				xPropertySub.setNamespaceURIs(nsMap);
    				List<Element> propertys =  xPropertySub.selectNodes(e);
    				
    				DefProperty defProperty = null;
    				for (Element e2 : propertys) {
    					String name = e2.attributeValue("name");
    					String ref = e2.attributeValue("ref");
    					String value = e2.attributeValue("value");
    					defProperty = new DefProperty(name, ref, value);
    					defBean.getDefPropertys().add(defProperty);
    				}
    				
    				defBeans.add(defBean);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    	}
    	public Object getBean(String key) {
    		return singltons.get(key);
    	}
    	
    	
    }
    

      

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
               
        <bean id="personDaoImpl" class="cn.gbx.dao.PersonDaoImpl"></bean>
     	<bean id="personServiceImpl" class="cn.gbx.serviceimpl.PersonServiceImpl" >
     		<property name="personDao" ref="personDaoImpl"></property>
     		<property name="name" value="ok-gbx"></property>
     		<property name="id" value="22"></property>
     	</bean>
    </beans>
    

      

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    阿里巴巴的零知识证明
    DPOS委托权益证明 vs POW工作量证明
    DPOS共识算法 -- 缺失的白皮书
    信息图:股份授权证明机制(DPOS)
    DPOS——回归中本聪
    深度解析POS和POW的区别
  • 原文地址:https://www.cnblogs.com/E-star/p/3558346.html
Copyright © 2011-2022 走看看