Spring第一天の代码学习
Spring底层示例
控制反转(IOC)概念
概念:所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转,目的是为了获得更好的扩展性和良好的可维护性。
依赖注入(DI)
概念:所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到另一个对象的组件中。
实体类Boy.java
package com.burns.bean;
public class Boy {
public void display(){
System.out.println("我是优秀的man");
}
}
实体类Girl.java
package com.burns.bean;
public class Girl {
private Boy boy;
public void setBoy(Boy boy) {
this.boy = boy;
}
public void kiss(){
boy.display();
System.out.println("执行kiss");
}
}
测试类App.java(通过main函数测试,当然也可以通过junit测试)
package com.burns.test;
import com.burns.bean.Girl;
import com.burns.context.ApplicationContext;
import com.burns.context.ClassPathXmlApplicationContext;
//测试类
public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Girl girl = (Girl)ac.getBean("girl");
girl.kiss();
}
}
定义接口 ApplicationContext.java
package com.burns.context;
import com.burns.bean.Girl;
public interface ApplicationContext {
Object getBean(String name);
}
定义接口的实现类ClassPathXmlApplicationContext.java
package com.burns.context;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class ClassPathXmlApplicationContext implements ApplicationContext {
Map<String, Object> map = new HashMap<String, Object>();
// 读取的spring容器的名称
private String filename;
/**
* @param string
*/
public ClassPathXmlApplicationContext(String filename) {
this.filename = filename;
//操作filename的xml文件
this.parseXML();
}
/**
* <?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="boy" class="com.itheima.bean.Boy"></bean>
<bean id="girl" class="com.itheima.bean.Girl">
<property name="boy" ref="boy"></property>
</bean>
</beans>
*
***
* 一 IOC原理:反射
* <bean id="boy" class="com.itheima.bean.Boy"></bean>
* <bean id="girl" class="com.itheima.bean.Girl">
* 创建对象,放置到Map<String,Object>集合中,
* key:String表示对象的唯一表示
* value:Object表示对象
*二:DI原理:内省
*<bean id="boy" class="com.itheima.bean.Boy"></bean>
<bean id="girl" class="com.itheima.bean.Girl">
<property name="boy" ref="boy"></property>
</bean>
* 将boongGirl对象提供的set方法,将对象传递给set方法
*/
private void parseXML() {
SAXReader reader = new SAXReader();
try {
Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(filename));
List<Node> beanList = document.selectNodes("beans/bean");
//遍历
if(beanList != null && beanList.size()>0){
for(Node node:beanList){
//bean节点的元素
Element element = (Element)node;
String idElement = element.attributeValue("id");
String classElement = element.attributeValue("class");
map.put(idElement, Class.forName(classElement).newInstance());
}
}
//使用内省完成注入
List<Node> propertyList =document.selectNodes("beans/bean/property");
//遍历
if(propertyList != null && propertyList.size()>0){
for(Node node:propertyList){
//property节点的元素
Element element = (Element)node;
String nameElement = element.attributeValue("name");//boay
String refElement = element.attributeValue("ref");//boy
//注入,读取父的对象(Girl)
//读取Girl对象;
Element parentElement = element.getParent();
String idParentElement = parentElement.attributeValue("id");
//从map集合中读取Girl对象
Object parentObject = map.get(idParentElement);//girl的对象提供set方法,被注入的对象
//内省
BeanInfo beanInfo = Introspector.getBeanInfo(parentObject.getClass(),Object.class);//内省机制完成的类,需要提供写的方法set,这里停用girl的getClass输出class
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
if(propertyDescriptors != null && propertyDescriptors.length>0){
for(PropertyDescriptor propertyDescriptor:propertyDescriptors){
String name = propertyDescriptor.getName();
System.out.println(name);
if(name != null && name.equals(name)){
//将boy对象写到Girl对象的set方法的属性中
propertyDescriptor.getWriteMethod().invoke(parentObject, map.get(refElement));//第一个参数是被注入的对象
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) {
return map.get(name);
}
}