Spring、Spring依赖注入与编码剖析Spring依赖注入的原理

来源:互联网 发布:新浪uc软件下载 编辑:程序博客网 时间:2024/05/29 17:17

Spring依赖注入

新建PersonIDao 和PersonDao底实现Save方法:

public interface PersonIDao {public void save();}

public class PersonDaoImpl  implements PersonIDao{@Overridepublic void save() {System.out.println("我是dao的Save方法");}}

在Bean.xml中注入PersonIDao,并将PersonIDao注入到PersonService中:

<bean id="personIDao" class="cn.dao.impl.PersonDaoImpl" /><bean id="personIService" class="cn.server.impl.PersonServiceImpl"><property name="personIDao" ref="personIDao" /></bean>


在PersonService中添加PersonIDao类型属性并实现属性的set方法,然后调用PersonIDao的save方法

public class PersonServiceImpl implements PersonIService {private PersonIDao personIDao;public PersonIDao getPersonIDao() {return personIDao;}public void setPersonIDao(PersonIDao personIDao) {this.personIDao = personIDao;}@Overridepublic void save() {personIDao.save();}}

然后测试:

@Testpublic void testSave() {AbstractApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");PersonIService personIService=(PersonIService)ac.getBean("personIService");personIService.save();}



编码剖析Spring依赖注入的原理

通过编码的方法式来剖析Spring 依赖注入的原理方法,新建PropertyDefinition类用来承载Bean中注入的property的属性:

public class PropertyDefinition {private String name;private String ref;public PropertyDefinition(){}public PropertyDefinition(String name, String ref) {super();this.name = name;this.ref = ref;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getRef() {return ref;}public void setRef(String ref) {this.ref = ref;}}

新建BeanDefinition用来承载解析到的Bean属性

public class BeanDefinition {private String id;private String className;private List<PropertyDefinition> properties=new ArrayList<PropertyDefinition>();public BeanDefinition(){}public BeanDefinition(String id, String className) {this.id = id;this.className = className;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public List<PropertyDefinition> getProperties() {return properties;}public void setProperties(List<PropertyDefinition> properties) {this.properties = properties;}}

新建OtherClassPathXMLApplicationContext 用来解析bean.xml

public class OtherClassPathXMLApplicationContext {private List<BeanDefinition> list=new ArrayList<BeanDefinition>();private Map<String,Object> beans=new HashMap<String, Object>();public OtherClassPathXMLApplicationContext(String fileName){this.readXML(fileName);this.instanceBeans();this.instanceProperties();}private void instanceBeans(){for(BeanDefinition bean : list){try {// 创建Bean实例,并放到Map中if(bean.getClassName()!=null && !bean.getClassName().trim().equals("")){beans.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());}} catch (Exception e) {e.printStackTrace();} }}private void instanceProperties(){for(BeanDefinition beanDefinition : list){Object bean=beans.get(beanDefinition.getId());if(bean!=null){ try {// 获取bean下所有的属性定义描述PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();for(PropertyDefinition propertyDefinition : beanDefinition.getProperties()){for(PropertyDescriptor propertyDescriptor : ps){// 如果bean下的属性名字与当前的BeanDefinition下的属性名称一样的话,则将引用对象注入到属性if(propertyDefinition.getName().equals(propertyDescriptor.getName())){Method setter=propertyDescriptor.getWriteMethod(); // 获取Bean的所有写入的方法 即 setter方法setter.setAccessible(true); // true: 直接访问私有属性,将例子中的私有属性改值。Object value=beans.get(propertyDefinition.getRef());setter.invoke(bean, value);  // 把引用对象注入属性break;}}}} catch (Exception e) {e.printStackTrace();}}}}private void readXML(String fileName){SAXReader saxReader = new SAXReader();Document doc=null;try{// JAVA里面对于类进行调用配置资源的文件数据,以this.getClass().getResourceAsStream()来读取比较合适。// 路径采用相对路径直接可以从工程的path路径去找。URL xmlpath=this.getClass().getClassLoader().getResource(fileName);doc=saxReader.read(xmlpath);Map<String,String> nsMap=new HashMap<String,String>(); nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空间XPath xsub=doc.createXPath("//ns:beans/ns:bean"); // 创建 beans/bean的查询路径xsub.setNamespaceURIs(nsMap); // 设置命名空间List beans=xsub.selectNodes(doc); // 获取文档下的所有bean节点for(Object node : beans){Element element=(Element)node;String id=element.attributeValue("id");String className=element.attributeValue("class");BeanDefinition bean=new BeanDefinition(id,className);// 编码剖析Spring依赖注入的原理// 加载bean下的PropertyXPath xproperty=element.createXPath("ns:property"); // 为xproperty 添加查询路径xproperty.setNamespaceURIs(nsMap);List properties=xproperty.selectNodes(element); // 查询出bean下的所有propertyfor(Object propertyNode : properties){Element propertyElement=(Element)propertyNode;String name=propertyElement.attributeValue("name");String ref=propertyElement.attributeValue("ref");bean.getProperties().add(new PropertyDefinition(name, ref));}list.add(bean);}}catch(Exception e){e.printStackTrace();}}// 通过Id名称,获取Beanpublic Object getBean(String name){return beans.get(name);}}

测试代码:

@Testpublic void testSave2() {OtherClassPathXMLApplicationContext ac = new OtherClassPathXMLApplicationContext("beans.xml");PersonIService personIService=(PersonIService)ac.getBean("personIService");personIService.save();}







0 0
原创粉丝点击