您的位置:首页 > 编程语言 > Java开发

传智播客Spring2.5视频教程_编码剖析Spring依赖注入的原理 1

2009-03-19 22:26 951 查看
成对出标色的地方 是保持一致的

<bean id="pesonDaoId" class="six.spring.service.impl.PersonDaoBean"></bean>
<bean id="personService"
class="six.spring.service.impl.PersonServiceBean" lazy-init="true">
<property name="personDaoBean" ref="pesonDaoId"></property>
</bean>

///////////////////////////////////////////////////////////////////////

package six.spring.service.impl;

import six.spring.service.PersonDao;
import six.spring.service.PersonService;

public class PersonServiceBean implements PersonService {
private PersonDao personDaoBean;

public void savePerson() {
System.out.println("我是包[six.spring.service.impl]的"
+ "类[PersonService]的[savePerson]方法");
this.personDaoBean.add();
}

public PersonDao getPersonDaoBean() {
return personDaoBean;
}

// 通过属性注入依赖对象的时候 必须给属性设置set方法
public void setPersonDaoBean(PersonDao personDaoBean) {
this.personDaoBean = personDaoBean;
}
}

///////////////////////////////////////////////////////////////////////////////////

以下传智播客Spring2.5视频教程_编码剖析Spring依赖注入的原理

老师只是讲了 具体实现 老师的实现 是 [万事万物皆对象]的一个小体现

从要解析的xml文件开始

<bean id="pesonDaoId" class="six.spring.service.impl.PersonDaoBean"></bean>
<bean id="personService"class="six.spring.service.impl.PersonServiceBean" lazy-init="true">
<property name="personDaoBeanAA" ref="pesonDaoId"></property>

<property name="personDaoBeanBB" ref="pesonDaoId"></property>
</bean>

看看,什么是对象? 万事万物皆对象 需求心中留

什么是需求呢? 解析xml 文件 ,得到反射的必要信息,

通过反射,实例化对象,在通过set 方法注入。

很明显了 一个元素 就是一个对象了

property对象 属性 name ref

bean 对象 属性 id class list<property>

/////////////////////////////////////////////////////////////////

package six.spring.application.beandefinition;

import java.util.ArrayList;
import java.util.List;

public class BeanDefinition {

private String id;
private String className;
private List<PropertyBeanDefinition> propertys = new ArrayList<PropertyBeanDefinition>();

// 将解析xml文件后的 结果 ,通过构造方法 实例化对象

// 构造方法里 不需要初始化被注如的属性

// 将List<PropertyBeanDefinition> propertys组装完毕后

// 通过set 方法设置
public BeanDefinition(String id, String clazz) {
this.id = id;
this.className = clazz;
}

省去set get 方法

/////////////////////////////////////////////////////////////////

ackage six.spring.application.beandefinition;

public class PropertyBeanDefinition {

private String name;
private String href;
public PropertyBeanDefinition(String name,String href) {
this.name = name;
this.href = href;

}

省去set get 方法

/////////////////////////////////////////////////////////////////

ackage six.spring.application;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import six.spring.application.beandefinition.BeanDefinition;
import six.spring.application.beandefinition.PropertyBeanDefinition;

public class ClassPathXMLApplicationContext {

private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
private Map<String, Object> objsMap = new HashMap<String, Object>();

public ClassPathXMLApplicationContext(String fileName)
throws ClassNotFoundException {
this.readXML(fileName);
this.instanceBeans();
}

private void instanceBeans() {
// 利用反射 生成对象
for (BeanDefinition beanDefinition : beanDefinitions) {
String className = beanDefinition.getClassName();
if (className != null && !"".equals(className.trim())) {
try {
// Class.forName(xxx.xx.xx) 返回的是一个类,
// newInstance() 后才创建一个对象
// Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类
// ,也就是说JVM会执行该类的静态代码段
Object object = Class.forName(className).newInstance();
objsMap.put(beanDefinition.getId(), object);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}

private void readXML(String fileName) {

SAXReader saxReader = new SAXReader();
Document document = null;
try {
System.out.println(fileName);
URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
System.out.println(xmlPath);
document = saxReader.read(xmlPath);
Map<String, String> nsMap = new HashMap<String, String>();

// 加入命名空间
nsMap.put("ns", "http://www.springframework.org/schema/beans");

// 创建beans/bean查询路径 注意 查询路径的写法
XPath xPath = document.createXPath("//ns:beans/ns:bean");

// 设置命名空间
xPath.setNamespaceURIs(nsMap);

//取得根元素下的所有节点
List<Element> beans = xPath.selectNodes(document);
for (Element element : beans) {
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
BeanDefinition beanDefinition = new BeanDefinition(id, clazz);

// 查找bean 接点的子接点property 不需要 带根路径
XPath xPathBeanDefinition = element.createXPath("ns:property");

// 设置命名空间
xPathBeanDefinition.setNamespaceURIs(nsMap);

//取得[Element]元素下的所有 节点 查找bean 接点的子接点property
List<Element> propertyBeans = xPathBeanDefinition.selectNodes(element);
for (Element propertyBean : propertyBeans) {

String name = propertyBean.attributeValue("name");
String ref = propertyBean.attributeValue("ref");

PropertyBeanDefinition propertyDefination = new PropertyBeanDefinition(name, ref);
beanDefinition.getPropertys().add(propertyDefination);
}
beanDefinitions.add(beanDefinition);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

ackage six.spring.junit;

import org.junit.BeforeClass;
import org.junit.Test;

import six.spring.application.ClassPathXMLApplicationContext;

public class SpringTest {

@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test
public void instanceSpring() {

try {
ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext("six/spring/junit/sixbeans.xml");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ackage six.spring.junit;

import org.junit.BeforeClass;
import org.junit.Test;

import six.spring.application.ClassPathXMLApplicationContext;

public class SpringTest {

@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test
public void instanceSpring() {

try {
ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext("six/spring/junit/sixbeans.xml");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

调试 过程 出现了一个bug

ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext("/six/spring/junit/sixbeans.xml");

异常信息

java.lang.NullPointerException
/six/spring/junit/sixbeans.xml
null
at org.dom4j.io.SAXReader.read(SAXReader.java:284)
at six.spring.application.ClassPathXMLApplicationContext.readXML(ClassPathXMLApplicationContext.java:55)
at six.spring.application.ClassPathXMLApplicationContext.<init>(ClassPathXMLApplicationContext.java:24)
at six.spring.junit.SpringTest.instanceSpring(SpringTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

/////////////////////////////////////////////////////////////////////////////////

null

发生异常的 位置

package six.spring.application;

System.out.println(fileName); // fileName = /six/spring/junit/sixbeans.xml
URL xmlPath = this.getClass().getClassLoader().getResource(fileName); // URL = null
如果 fileName 是 six/spring/junit/sixbeans.xml 的话 就没有问题了。

因为 根目录 this.getClass().getClassLoader() 得到根目录 就是 存放class 的 bin 目录

涉及到的知识点 我 在下一篇 《getClass().getClassLoader().getResource(path) 相关》 写一些 自己查到的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: