Spring的DI(Ioc) - 注入bean 和 基本数据类型
注入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>