PersonService.java
Java代码
package cn.itcast.service;
public interface PersonService {
public void save();
}
PersonServiceBean.java
package cn.itcast.service.impl;
import cn.itcast.service.PersonService;
public class PersonServiceBean implements PersonService {
public void save(){
System.out.println("传智播客版容器: 我是save()方法");
}
}
package cn.itcast.service;
public interface PersonService {
public void save();
}
PersonServiceBean.java
package cn.itcast.service.impl;
import cn.itcast.service.PersonService;
public class PersonServiceBean implements PersonService {
public void save(){
System.out.println("传智播客版容器: 我是save()方法");
}
}
BeanDefinition.java
Java代码
package junit.test;
/*
* 在读取配置文件的时候,我们会把读取到bean的信息存放在这个javabean对象里面去
* */
public class BeanDefinition {
private String id;
private String className;
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;
}
}
package junit.test;
/*
* 在读取配置文件的时候,我们会把读取到bean的信息存放在这个javabean对象里面去
* */
public class BeanDefinition {
private String id;
private String className;
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;
}
}beans.xml
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="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>
</beans>
<?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="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>
</beans>
前面我们学习了怎样把bean交给Spring容器管理,怎样从Spring容器获取bean实例,相信大家肯定会有很多疑问,其中一个疑问是: Spring容器内部怎么帮我们创建,管理bean的?
接下来解说一下,到底Spring容器内部是如何创建bean的。 我们模拟Spring容器,来建一个传智播客版的Spring容器
ItcastClassPathXMLApplicationContext.java
Java代码
package junit.test;
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;
/**
* 传智播客版的Spring容器
*/
public class ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
// 存放bean实例
public ItcastClassPathXMLApplicationContext(String filename) {
// 模拟内部的实现,首先要读取配置文件,可以用dom4j
this.readXML(filename);
// 读取完bean之后,Spring要对bean进行实例化,怎么实现实例化呢? 通过反射机制就很容易做到
this.instanceBeans();
}
/**
* 实现bean的实例化
*/
private void instanceBeans() {
for (BeanDefinition beanDefinition : beanDefines) {
try {
if (beanDefinition.getClassName() != null
&& !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(
beanDefinition.getClassName()).newInstance());
// 通过反射技术把bean都创建出来
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 读取xml配置文件
*
* @param filename
*/
private void readXML(String filename) {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
URL xmlpath = this.getClass().getClassLoader()
.getResource(filename);
document = saxReader.read(xmlpath);
Map<String, String> nsMap = new HashMap<String, String>();
nsMap.put("ns", " 加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);// 设置命名空间
List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点
for (Element element : beans) {
String id = element.attributeValue("id");// 获取id属性值
String clazz = element.attributeValue("class"); // 获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
beanDefines.add(beanDefine);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取bean实例
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
return this.sigletons.get(beanName);
}
}
package junit.test;
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;
/**
* 传智播客版的Spring容器
*/
public class ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
// 存放bean实例
public ItcastClassPathXMLApplicationContext(String filename) {
// 模拟内部的实现,首先要读取配置文件,可以用dom4j
this.readXML(filename);
// 读取完bean之后,Spring要对bean进行实例化,怎么实现实例化呢? 通过反射机制就很容易做到
this.instanceBeans();
}
/**
* 实现bean的实例化
*/
private void instanceBeans() {
for (BeanDefinition beanDefinition : beanDefines) {
try {
if (beanDefinition.getClassName() != null
&& !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(
beanDefinition.getClassName()).newInstance());
// 通过反射技术把bean都创建出来
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 读取xml配置文件
*
* @param filename
*/
private void readXML(String filename) {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
URL xmlpath = this.getClass().getClassLoader()
.getResource(filename);
document = saxReader.read(xmlpath);
Map<String, String> nsMap = new HashMap<String, String>();
nsMap.put("ns", "
XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);// 设置命名空间
List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点
for (Element element : beans) {
String id = element.attributeValue("id");// 获取id属性值
String clazz = element.attributeValue("class"); // 获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
beanDefines.add(beanDefine);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取bean实例
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
return this.sigletons.get(beanName);
}
}
之后做下测试:看从传智播客版的容器里是否能够取到bean实例?
SpringTest.java
Java代码
package junit.test;
import org.junit.BeforeClass;
import org.junit.Test;
import cn.itcast.service.PersonService;
public class SpringTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test public void instanceSpring(){
ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
PersonService personService = (PersonService)ctx.getBean("personService");
personService.save();
}
}
package junit.test;
import org.junit.BeforeClass;
import org.junit.Test;
import cn.itcast.service.PersonService;
public class SpringTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test public void instanceSpring(){
ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
PersonService personService = (PersonService)ctx.getBean("personService");
personService.save();
}
}
运行单元测试,打印结果是
传智播客版容器: 我是save()方法
这句话是业务方法打印出来的。
在控制台里,我们通过传智播客版的Spring容器取到了bean实例,并且成功的调用了它的save方法。 这里大家就可以了解,到底Spring内部是如何创建和管理bean的,当然这只是个模拟的代码,实际中可能要处理的情况还是很复杂,这例子是为了便于大家理解