主要内容参考 http://www.cnblogs.com/fingerboy/p/5425813.html
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。即Spring管理对象生命周期及依赖关系
程序中所有的Bean之间的依赖关系我们是放在一个xml文件中进行维护的,就是applicationContext.xml
ConfigManager类完成的功能是读取xml,并将所有读取到有用的信息封装到我们创建的一个Map<String,Bean>集合中,用来在初始化容器时创建bean对象.
定义一个BeanFactory的接口,接口中有一个getBean(String name)方法,用来返回你想要创建的那个对象.
然后定义一个该接口的实现类ClassPathXmlApplicationContext.就是在这个类的构造方法中,初始化容器,通过调用ConfigManager的方法返回的Map集合,通过反射一一创建bean对象.这里需要注意,对象的创建有两个时间点,这取决与bean标签中scope属性的值:
如果scope="singleton",那么对象在容器初始化时就已创建好,用的时候只需要去容器中取即可.
如果scope="prototype",那么容器中不保存这个bean的实例对象,每次开发者需要使用这个对象时再进行创建.
实体类 Student Teacher
package com.entity;
public class Teacher {
private String name;
private Student student;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public String toString() {
return "Teacher [name=" + name + ", student=" + student + "]";
}
public Teacher(String name, Student student) {
super();
this.name = name;
this.student = student;
}
public Teacher() {
super();
}
}
package com.entity;
public class Student {
private String name;
private Integer age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String toString() {
return "Student [name=" + name + ", age=" + age + ", address="
+ address + "]";
}
}
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- <bean id="str" class="com.lang.String"></bean> -->
<bean id="teacher" class="com.entity.Teacher" scope="prototype">
<property name="name" value="肖肖"></property>
<property name="student" ref="student"></property>
</bean>
<bean id="student" class="com.entity.Student">
<property name="name" value="小明"></property>
<property name="age" value="1"></property>
<property name="address" value="陕西临潼"></property>
</bean>
</beans>
用于封装Bean标签的类 Bean
package com.config;
import java.util.ArrayList;
import java.util.List;
public class Bean {
private String name;
private String className;
private String scope="singleton";
private List<Property> properties=new ArrayList<Property>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public List<Property> getProperties() {
return properties;
}
public void setProperties(List<Property> properties) {
this.properties = properties;
}
}
用于封装Bean子标签 Property
package com.config;
public class Property {
private String name;
private String value;
private String ref;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public String toString() {
return "Property [name=" + name + ", value=" + value + ", ref=" + ref
+ "]";
}
}
解析xml文件的ConfigManager类
package com.config.parse;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.config.Bean;
import com.config.Property;
public class ConfigManager {
private static Map<String,Bean> map=new HashMap<String,Bean>();
public static Map<String,Bean> getConfig(String path){
//xml解析器
SAXReader reader=new SAXReader();
InputStream in=ConfigManager.class.getResourceAsStream(path);
Document doc=null;
try {
doc=reader.read(in);
} catch (DocumentException e) {
e.printStackTrace();
System.out.println("初始化出错");
}
//从任意节点的位置查找bean节点
String xpath="//bean";
List<Element> beans=doc.selectNodes(xpath);
if(beans!=null){
for(Element beanElement:beans){
Bean bean=new Bean();
String name=beanElement.attributeValue("id");
String className=beanElement.attributeValue("class");
String scope=beanElement.attributeValue("scope");
bean.setName(name);
bean.setClassName(className);
if(scope!=null){
bean.setScope(scope);
}
List<Element> properties=beanElement.elements("property");
if(properties!=null){
for(Element propertyElement:properties){
Property property=new Property();
String pname=propertyElement.attributeValue("name");
String pvalue=propertyElement.attributeValue("value");
String pref=propertyElement.attributeValue("ref");
property.setName(pname);
property.setValue(pvalue);
property.setRef(pref);
bean.getProperties().add(property);
}
}
map.put(name, bean);
}
}
return map;
}
}
注入属性的工具类 InjectUtil
package com.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InjectUtil {
//注入value
public static void injectValue(Object obj,String name,String value){
Method[] methods=obj.getClass().getMethods();
String methodName="set"+name.substring(0, 1).toUpperCase()+name.substring(1);
for(Method method:methods){
if(method.getName().equals(methodName)){
Class<?>[] parameters=method.getParameterTypes();
Class<?> parameter=parameters[0];
try {
Object paraObj=parameter.getConstructor(String.class).newInstance(value);
method.invoke(obj, paraObj);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException
| InvocationTargetException | NoSuchMethodException
| SecurityException e) {
e.printStackTrace();
}
}
}
}
//注入ref
public static void injectRef(Object obj,String name,Object ref){
Method[] methods=obj.getClass().getMethods();
String methodName="set"+name.substring(0,1).toUpperCase()+name.substring(1);
for(Method method:methods){
if(method.getName().equals(methodName)){
try {
method.invoke(obj, ref);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
BeanFacroty接口
package com.main;
public interface BeanFactory {
public Object getBean(String name);
}
ApplicationContext类
package com.main;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.config.Bean;
import com.config.Property;
import com.config.parse.ConfigManager;
import com.utils.InjectUtil;
public class ClassPathXmlApplicationContext implements BeanFactory{
//读取配置文件的map
private Map<String,Bean> configMap;
private Map<String,Object> context=new HashMap<String,Object>();
public ClassPathXmlApplicationContext(String path){
configMap=ConfigManager.getConfig(path);
for(Entry<String,Bean> entry:configMap.entrySet()){
String name=entry.getKey();
Bean bean=entry.getValue();
Object obj=context.get(name);
if(obj==null&&bean.getScope().equals("singleton")){
obj=createBean(bean);
context.put(name, obj);
}
}
}
public Object createBean(Bean bean){
String className=bean.getClassName();
Class<?> c=null;
try {
c=Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object obj=null;
try {
obj=c.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
List<Property> properties=bean.getProperties();
if(properties!=null){
for(Property property:properties){
String name=property.getName();
String value=property.getValue();
String ref=property.getRef();
if(value!=null){
InjectUtil.injectValue(obj, name,value);
}
if(ref!=null){
Object propertyObj=context.get(ref);
if(context.get(ref)==null){
propertyObj=createBean(configMap.get(ref));
if(configMap.get(ref).getScope().equals("singleton")){
context.put(ref,propertyObj);
}
}
InjectUtil.injectRef(obj,ref,propertyObj);
}
}
}
return obj;
}
public Object getBean(String name){
Bean bean=configMap.get(name);
if(bean.getScope().equals("singleton")){
return context.get(name);
}else{
return createBean(bean);
}
}
}
测试类
package com.test;
import com.entity.Student;
import com.entity.Teacher;
import com.main.BeanFactory;
import com.main.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args){
BeanFactory context=
new ClassPathXmlApplicationContext("/ApplicationContext.xml");
Student student1=(Student)context.getBean("student");
Student student2=(Student)context.getBean("student");
System.out.println(student1);
System.out.println(student1==student2);
Teacher teacher1=(Teacher)context.getBean("teacher");
Teacher teacher2=(Teacher)context.getBean("teacher");
System.out.println(teacher1);
System.out.println(teacher1==teacher2);
String s = "";
}
}
测试结果
Student [name=小明, age=1, address=陕西临潼]
true
Teacher [name=肖肖, student=Student [name=小明, age=1, address=陕西临潼]]
false
只有单例模式容器才会持有该对象的引用,若是原型模式只有客户端持有该对象的引用