spring IOC 源码和demo

一、IOC

  “控制反转(IoC)”也称为“依赖注入(DI)”,是一个定义对象依赖的过程,对象只和 构造参数,工厂方法参数,对象实例属性或工厂方法返回相关。容器在创建这些 bean 的时 候注入这些依赖。这个过程是一个反向的过程,所以命名为依赖反转,对象实例的创建由其 提供的构造方法或服务定位机制来实现。

  IOC 最大的好处就是“解耦”。

二、IOC底层原理使用技术

  1、xml配置文件,dom4j解析配置的xml文件

       2、注解处理。spring4 和spring boot 大量使用注解,简化了bean的配置。

  3、工厂、策略、委托等设计模式

  4、反射

  5、动态代理(JDK自带动态代理(实现了接口的类)、CGLib(未实现接口的类))

三、Spring容器基本概念

  Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。 Spring 的 IoC 容器在完成这些底层工作的基础上,还提供了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。

  BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;

  ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory。

 

   BeanDefinition  是描述bean的类,容器通过一个Map持有BeanDefinition。

  private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);//key为beanName;

四、IOC demo

Spring的源码,看的出来,源码异常复杂,这是因为Spring的设计者需要考虑到框架的扩展性,健壮性,性能等待元素,因此设计的很复杂。

因此实现一个简单的 IOC,让我们更加深刻的理解IOC,因此,有了这篇文章。

当然我们是仿照Spring 的 IOC,因此代码命名和设计基本是仿照spring的。

我们将分为几步来编写简易 IOC,首先设计组件,再设计接口,然后关注实现。

BeanFactory 容器,BeanDefinition Bean的基本数据结构,当然还需要加载Bean的资源加载器。大概最重要的就是这几个组件。容器用来存放初始化好的Bean,BeanDefinition 就是Bean的基本数据结构,比如Bean的名称,Bean的属性 PropertyValue,Bean的方法,是否延迟加载,依赖关系等。资源加载器就简单了,就是一个读取XML配置文件的类,读取每个标签并解析。

首先肯定需要一个BeanFactory,就是Bean容器,容器接口至少有2个最简单的方法,一个是获取Bean,一个注册Bean.

public interface BeanFactory {

  /**
   * 根据bean的名称从容器中获取bean对象
   *
   * @param name bean 名称
   * @return bean实例
   * @throws Exception 异常
   */
  Object getBean(String name) throws Exception;

  /**
   * 将bean注册到容器中
   *
   * @param name bean 名称
   * @param bean bean实例
   * @throws Exception 异常
   */
  void registerBeanDefinition(String name, BeanDefinition bean) throws Exception;
}

一个最简单 BeanDefinition 接口,我们为了方便,但因为我们这个不必考虑扩展,因此可以直接设计为类,BeanDefinition 需要哪些元素和方法呢? 需要一个 Bean 对象,一个Class对象,一个ClassName字符串,还需要一个元素集合 PropertyValues

public class BeanDefinition {

  /**
   * bean
   */
  private Object bean;

  /**
   * bean 的 CLass 对象
   */
  private Class beanClass;

  /**
   * bean 的类全限定名称
   */
  private String ClassName;

  /**
   * 类的属性集合
   */
  private PropertyValues propertyValues = new PropertyValues();

  /**
   * 获取bean对象
   */
  public Object getBean() {
    return this.bean;
  }

  /**
   * 设置bean的对象
   */
  public void setBean(Object bean) {
    this.bean = bean;
  }

  /**
   * 获取bean的Class对象
   */
  public Class getBeanclass() {
    return this.beanClass;
  }

  /**
   * 通过设置类名称反射生成Class对象
   */
  public void setClassname(String name) {
    this.ClassName = name;
    try {
      this.beanClass = Class.forName(name);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * 获取bean的属性集合
   */
  public PropertyValues getPropertyValues() {
    return this.propertyValues;
  }

  /**
   * 设置bean的属性
   */
  public void setPropertyValues(PropertyValues pv) {
    this.propertyValues = pv;
  }

}

一个容器实现:

public class AutowireBeanFactory extends AbstractBeanFactory {


  /**
   * 根据bean 定义创建实例, 并将实例作为key, bean定义作为value存放,并调用 addPropertyValue 方法 为给定的bean的属性进行注入
   */
  @Override
  protected Object doCreate(BeanDefinition beandefinition) throws Exception {
    Object bean = beandefinition.getBeanclass().newInstance();
    addPropertyValue(bean, beandefinition);
    return bean;
  }

  /**
   * 给定一个bean定义和一个bean实例,为给定的bean中的属性注入实例。
   */
  protected void addPropertyValue(Object bean, BeanDefinition beandefinition) throws Exception {
    // 循环给定 bean 的属性集合
    for (PropertyValue pv : beandefinition.getPropertyValues().getPropertyValues()) {
      // 根据给定属性名称获取 给定的bean中的属性对象
      Field declaredField = bean.getClass().getDeclaredField(pv.getname());
      // 设置属性的访问权限
      declaredField.setAccessible(true);
      // 获取定义的属性中的对象
      Object value = pv.getvalue();
      // 判断这个对象是否是 BeanReference 对象
      if (value instanceof BeanReference) {
        // 将属性对象转为 BeanReference 对象
        BeanReference beanReference = (BeanReference) value;
        // 调用父类的 AbstractBeanFactory 的 getBean 方法,根据bean引用的名称获取实例,此处即是递归
        value = getBean(beanReference.getName());
      }
      // 反射注入bean的属性
      declaredField.set(bean, value);
    }

  }

}
 abstract class AbstractBeanFactory implements BeanFactory {

  /**
   * 容器
   */
  private HashMap<String, BeanDefinition> map = new HashMap<>();

  /**
   * 根据bean的名称获取bean, 如果没有,则抛出异常 如果有, 则从bean定义对象获取bean实例
   */
  @Override
  public Object getBean(String name) throws Exception {
    BeanDefinition beandefinition = map.get(name);
    if (beandefinition == null) {
      throw new IllegalArgumentException("No bean named " + name + " is defined");
    }
    Object bean = beandefinition.getBean();
    if (bean == null) {
      bean = doCreate(beandefinition);
    }
    return bean;
  }

  /**
   * 注册 bean定义 的抽象方法实现,这是一个模板方法, 调用子类方法doCreate,
   */
  @Override
  public void registerBeanDefinition(String name, BeanDefinition beandefinition) throws Exception {
    Object bean = doCreate(beandefinition);
    beandefinition.setBean(bean);
    map.put(name, beandefinition);
  }

  /**
   * 减少一个bean
   */
  abstract Object doCreate(BeanDefinition beandefinition) throws Exception;
}

github地址:IOC demo

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值