自定义IOC的实现:
没有使用IOC技术的环境:
1.创建工程customIoc,添加依赖(需要添加解析xml的依赖):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it</groupId>
<artifactId>customIoc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- 解析 xml 的 dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- dom4j 的依赖包 jaxen -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
2.三层框架模拟:
2.1 web层
package com.it.web;
import com.it.service.UserService;
import org.junit.Test;
/**
* ToDo
* @author Lyle
* @date 2020/9/5
*/
public class UserServlet {
@Test
public void doGet(){
//获取请求参数
//调用业务
UserService userService = new UserService();
userService.test();
//响应结果
}
}
2.2 service层
package com.it.service;
import org.junit.Test;
/**
* ToDo
*
* @author Lyle
* @date 2020/9/5
*/
public class UserService {
/**
* 注册
*/
public void test(){
System.out.println("调用UserDao中的save方法。。。。");
}
}
2.3 dao层:接口+实现类
public interface UserDao {
void save();
}
public class UserDaoImpl implements UserDao {
public void save(){
System.out.println("save方法保存");
}
}
使用IOC技术:
IOC实现:xml+工厂模式+反射
1.xml配置:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!--id属性,作为bean的惟一标识,一般写接口或者类的名字,首字母小写;
class属性:写类的全路径名-->
<bean id="userDao" class="com.it.dao.impl.UserDaoImpl">
</bean>
</beans>
2.工厂对象:BeanFactory
工厂对象解析xml,获取类的全路径名,然后通过反射创建对象,存入Map容器中;
简单版:
缺点:
每次getBean都需要读取文件;
临时使用的时候才使用反射创建(反射的效率比new要慢)
package com.it.utils;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.IOException;
import java.io.InputStream;
/**
* ToDo
*
* @author Lyle
* @date 2020/9/6
*/
public class BeanFactory {
public static Object getBean(String id){
InputStream is=null;
try {
//1.创建SAXReader对象
SAXReader saxReader = new SAXReader();
//2.读取xml,获得document对象
//获取文件流对象
is = BeanFactory.class.getClassLoader().getResourceAsStream("applicationContext.xml");
Document document = saxReader.read(is);
//3.根据id获得bean标签
Element beanEle = (Element) document.selectSingleNode("//bean[@id='"+id +"']");
//4.获得bean标签的class属性值
String className = beanEle.attributeValue("class");
//System.out.println(className);
//5.根据class属性值(类的全路径名)通过反射创建对象返回
Class clazz = Class.forName(String.valueOf(className));
Object obj = clazz.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}finally {
if (is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/* public static void main(String[] args) {
BeanFactory.getBean("userDao");
}*/
}
获取对象时通过这个工厂对象的静态方法获取对象:
UserDao userDao= (UserDao) BeanFactory.getBean("userDao");
终极版:
将读取文件放入静态代码块,只读取一次;
程序初始化的时候,创建好对象放入Map容器中,使用时直接从Map容器中获取;
package com.it.utils;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*SpringIOC 工厂对象:读取和解析xml,通过反射创建对象存入Map容器中
* @author Lyle
* @date 2020/9/6
*/
public class BeanFactory {
//Map容器
public static Map<String,Object> beanMap=new HashMap<>();
//静态代码块,解析xml,反射创建对象存入Map容器中
static {
InputStream is=null;
try {
//1.创建SAXReader对象
SAXReader saxReader = new SAXReader();
//2.读取xml,获得document对象
//获取文件流对象
is = BeanFactory.class.getClassLoader().getResourceAsStream("applicationContext.xml");
Document document = saxReader.read(is);
//获得所有的bean标签,遍历创建好对象存入Map容器中
List<Element> baenEles = document.selectNodes("//bean");
//遍历
for (Element baenEle : baenEles) {
//获得bean标签的id和class属性值
String id = baenEle.attributeValue("id");
String className = baenEle.attributeValue("class");
//根据class属性值,通过反射创建好对象存入Map中
Object clzss = Class.forName(className).newInstance();
beanMap.put(id,clzss);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static Object getBean(String id){
return beanMap.get(id);
}
}