实例工厂(也是用了抽象工厂模式和单例模式去设计实现IOC)
package cn.edu.guet.myblog.ioc;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author pangjian
* @ClassName BeanFactory
* @Description 实例工厂,读取applicationContext.xml文件通过反射创建对象
* @date 2021/7/1 22:10
*/
public class BeanFactory {
// 单例模式
private static BeanFactory instance = new BeanFactory();
private BeanFactory(){
}
public static BeanFactory getInstance(){
return instance;
}
/**
* @Description: 通过id拿到已创建好的实例对象
* @Param id: 配置文件中的id
* @return java.lang.Object
* @date 2021/7/2 13:31
*/
public Object getBean(String id){
return map.get(id);
}
/**
* @Description: key:配置文件bean的id value:用id对应的全类名通过反射创建的对象
* @date 2021/7/2 13:09
*/
public static Map<String,Object> map = new HashMap<>();
/**
* @Description:通过反射创建对象,元素参数ele其实就是bean元素
* @Param ele:
* @return void
* @date 2021/7/2 12:51
*/
public static void parseElement(Element ele){
Object bean = null;
Class clazz = null;
try {
String id = ele.attributeValue("id");
if(map.get(id) == null){ // 还没创建id=testService对象,进入
clazz = Class.forName(ele.attributeValue("class")); // 拿到对象id的全类名,通过反射创建对象
bean = clazz.newInstance();
map.put(id,bean);
}
Object obj = null;
String ref = "";
List<Element> childElements = ele.elements(); // 得到ele的子元素,也就是bean标签的子元素
for (Element childEle:
childElements) {
ref = childEle.attributeValue("ref"); // 得到属性名对应要注入的属性类型id
obj = map.get(ref); // 通过id在已创建的对象中获取
if(obj == null){ // 判断该类型对象是否已经创建,空则要创建
for (Element el:
list) {
// 遍历配置文件中所有的bean标签
String ids = el.attributeValue("id");
if(ids.equals(ref)){ // 判断其他bean标签的id是否是属于该属性需要的类型id
parseElement(el);// 如果是则递归调用反射创建对象
}
}
}
obj = map.get(ref);
if(clazz != null){
Method[] methods = clazz.getDeclaredMethods();
for (Method m:
methods) {
// 关联的属性对象通过set方法注入到该实例的属性中,setDog(),全部转为小写,是否包含ref代表的值。
if(m.getName().startsWith("set") && m.getName().toLowerCase().contains(ref.toLowerCase())){
m.invoke(bean,obj);
}
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
static List<Element> list;
/**
* @Description:加载配置文件,调用parseElement()方法创建对象;
* @date 2021/7/2 13:02
*/
static {
try {
SAXReader reader = new SAXReader();
InputStream in = Class.forName("cn.edu.guet.myblog.ioc.BeanFactory").getResourceAsStream("/applicationContext.xml");
Document doc = reader.read(in);
list = doc.selectNodes("/beans/bean");
for(Element ele : list){
parseElement(ele);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
监听器
package cn.edu.guet.myblog.mvc;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.net.URISyntaxException;
import java.util.Map;
/**
* @Description: 监听器
* @date 2021/6/27 10:34
*/
@WebListener()
public class ContextConfigListener implements ServletContextListener {
public ContextConfigListener() {
}
public void contextInitialized(ServletContextEvent sce) {
try {
Map<String, ControllerMapping> controllerMapping = new Configuration().config();
sce.getServletContext().setAttribute("cn.guet.web.controller", controllerMapping);
Class.forName("cn.edu.guet.myblog.ioc.BeanFactory");
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent sce) {
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<!--测试bean配置文件-->
<bean id="testService" class="cn.edu.guet.myblog.service.impl.TestServiceImpl">
<property name="testMapper" ref="testMapper"></property>
</bean>
<bean id="testMapper" class="cn.edu.guet.myblog.mapper.TestMapper"></bean>
<bean id="testController" class="cn.edu.guet.myblog.controller.TestController">
<property name="testService" ref="testService"></property>
</bean>
<bean id="testService" class="cn.edu.guet.myblog.service.impl.TestServiceImpl">
<property name="testMapper" ref="testMapper"></property>
</bean>
<!--结束-->
</beans>