将各层之间的依赖对象赋值为null,降低耦合。
1、将层与层之间的依赖写在配置文件中,application.xml文件信息如下
<?xml version="1.0" encoding="utf-8"?>
<beans>
<bean id="fruitDAO" class="com.atguigu.fruit.dao.impl.FruitDAOImpl"/>
<bean id="fruitService" class="com.atguigu.fruit.service.impl.FruitServiceImpl">
<!-- property标签用来表示属性;name表示属性名;ref表示引用其他bean的id值-->
<property name="fruitDAO" ref="fruitDAO"/>
</bean>
<bean id="fruit" class="com.atguigu.fruit.controllers.FruitController">
<property name="fruitService" ref="fruitService"/>
</bean>
</beans>
<!--
Node 节点
Element 元素节点
Text 文本节点
<sname>jim</sname>
-->
配置文件中id=fruitDAO告诉应用程序fruitDAO对象所对应的是FruitDAOImpl,同理fruitService对象对应的类是FruitServiceImpl。
property标签中,ref="fruitDAO"表示引用其他bean标签中id=fruitDAO所对应的类(例如FruitServiceeImpl),name="fruitService"表示该类中有一个对象命名为fruitService。
2、创建beanFactory接口,在接口中创建getBean方法,创建classPatchApplicationContext类实现beanFactory接口,在构造方法中创建读取配置文件信息,并存放在Map集合中。
beanFactory接口:
public interface BeanFactory {
Object getBean(String id);
}
classPatchApplicationContext类:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class ClassPathXmlApplicationContext implements BeanFactory{
private Map<String,Object> beanMap=new HashMap<>();
public ClassPathXmlApplicationContext(){
try {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
//1.创建DocumentBuilderFactory
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//2.创建DocumentBuilder对象
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder() ;
//3.创建Document对象
Document document = documentBuilder.parse(inputStream);
//4.获取所有的bean节点
NodeList beanNodeList = document.getElementsByTagName("bean");
for(int i = 0 ; i<beanNodeList.getLength() ; i++){
Node beanNode = beanNodeList.item(i);
if(beanNode.getNodeType() == Node.ELEMENT_NODE){
Element beanElement = (Element)beanNode ;
String beanId = beanElement.getAttribute("id");
String className = beanElement.getAttribute("class");
Class beanClass = Class.forName(className);
//创建bean实例
Object beanObj = beanClass.newInstance() ;
//将bean实例对象保存到map容器中,到目前为止,bean与bean之间的依赖关系还有设置
beanMap.put(beanId , beanObj) ;
}
}
//5、组装bean之间的依赖关系
for(int i = 0 ; i<beanNodeList.getLength() ; i++){
Node beanNode = beanNodeList.item(i);
if(beanNode.getNodeType() == Node.ELEMENT_NODE){
Element beanElement = (Element)beanNode ;//获取bean节点
String beanId = beanElement.getAttribute("id");
NodeList beanChildNodeList=beanElement.getChildNodes();//获取当前bean节点下的子节点(property)
//遍历子节点,找出元素节点切元素节点名称为property
for(int j=0;j<beanChildNodeList.getLength();j++){
Node beanChildNode=beanChildNodeList.item(j);
if(beanChildNode.getNodeType()==Node.ELEMENT_NODE&&"property".equals(beanChildNode.getNodeName())){
Element propertyElement=(Element) beanChildNode;
String propertyName=propertyElement.getAttribute("name");
String propertyRef=propertyElement.getAttribute("ref");
//1)、找到propertyRef对应的实例
Object refObj=beanMap.get(propertyRef);
//2)、将refObj设置到当前bean对应的实例的property属性上去
Object beanObj=beanMap.get(beanId);
Class beanClazz=beanObj.getClass();
Field propertyField=beanClazz.getDeclaredField(propertyName);
propertyField.setAccessible(true);
propertyField.set(beanObj,refObj);
}
}
String className = beanElement.getAttribute("class");
Class beanClass = Class.forName(className);
//创建bean实例
Object beanObj = beanClass.newInstance() ;
//将bean实例对象保存到map容器中,到目前为止,bean与bean之间的依赖关系还有设置
beanMap.put(beanId , beanObj) ;
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
@Override
public Object getBean(String id) {
return beanMap.get(id);
}
}
3、在中央控制器类中创建classPatchApplicationContext类对象,在初始化方法中实例化classPatchApplicationContext类对象,方便获取Map集合中的数据。
private BeanFactory beanFactory;
public DispatcherServlet(){
}
public void init() throws ServletException {
super.init();
beanFactory=new ClassPathXmlApplicationContext();
}