IOC (控制反转Inversion of control)是spring的一个重要特性,本文通过一个简单的例子来理解这种特性
我是这样理解IOC的:
IOC是指控制权的转移,在一个普通的类中,需要用到一些其他类的对象,正常情况下要使用它们,首先应该创建它,否则就无法使用,这在一段不长的代码中自然没有什么问题,人脑可以轻松处理这些问题.然而随着开发进行创建的东西越来越多,各个部分的依赖会变得越来越复杂,处理这些就会非常的困难.
我们自然不想处理这些复杂的关系,这会让人的脑袋爆炸的.对于这种问题,由计算机来处理才是应该的.IOC就是处理这种问题的方法.
我们不需要考虑对象是怎么创建的,只要用到的时候从一个容器中获取就行.Spring就是这样一个容器.
下面我们来做一个简单的容器,我们只需要把名字给它,就能从里面获取到对象.
首先新建两个我们想要获取的简单的类
public class MyOrder {
private OrderDao orderDao;
public void print(){
System.out.println("print");
orderDao.select;
}
}
public class OrderDao {
private String name="hello";
public void select(){
System.out.println("select");
}
}
新建一个properties配置文件,在里面配置这两个类的bean名称和类
myOrder=cn.acgq.MyOrder
orderDao=cn.acgq.OrderDao
使用反射来加载类,创建对象,将其放到Map中去
public class BeanFactory {
private static Map<String, Object> beans = new HashMap<>();
//创建bean名字和类的映射
static {
//加载配置文件
try {
properties.load(BeanFactory.class.getResourceAsStream("/config.properties"));
} catch (IOException e) {
throw new RuntimeException(e);
}
properties.load(this.class.getResourceAsStream("/config.properties"));
properties.forEach((bean, beanClass) -> {
try {
//根据配置文件创建bean,将其放到Map中去
Class clazz = Class.forName((String) beanClass);
Object beanInstance = clazz.getConstructor().newInstance();
beans.put((String) bean,beanInstance);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
//依赖注入
// beans.forEach((beanName,beanInstance) ->
// dependencyInjection(beanName,beanInstance,beans));
}
public static Object getBean(String beanName){
return beans.get(beanName);
}
}
这样我们就能从beanFactory中根据名称获取bean了.
MyOrder myOrder= (MyOrder) BeanFactory.getBean("myOrder");
不过这样还有一个问题,MyOrder中的orderDao为空,如果执行print方法会报错.
我们还需要把beanFactory中生成的类注入给它
新建一个注释,表示需要自动注入
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Resources {
}
在MyOrder中的OrderDao上添加注释
新建方法 dependencyInjection进行注入,同样是用反射
private static void dependencyInjection(String beanName, Object beanInstance,Map<String,Object> beans) {
//过滤出需要注入的字段
List<Field> fieldToBeAutowired =
Stream.of(beanInstance.getClass().getDeclaredFields())
.filter(field -> field.isAnnotationPresent(Resources.class))
.collect(Collectors.toList());
fieldToBeAutowired.forEach(field -> {
String fieldName=field.getName();
field.setAccessible(true);//private字段需要进行这一操作
Object dependencyBeanInstance = beans.get(fieldName);
try {
//设置field
field.set(beanInstance,dependencyBeanInstance);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
这样我们就自己完成了一个简单的IOC容器.
个人对IOC和DI的简单理解,知识浅薄,难免有些疏漏,请不吝指正.
原文:https://www.cnblogs.com/acgq/p/11645320.html