zoukankan      html  css  js  c++  java
  • 手写Spring mvc框架 (二)

    五、控制反转(IOC)和依赖注入(DI)
    1. 概念

      • 控制反转:将创建对象的控制权反转给了spring

      • 依赖注入:spring在创建对象的过程中,动态地将依赖对象注入到Bean组件

    2. 实现

      工厂模式-BeanFactory

      从BeanFactory中获取对象,没有就创建,依赖没有就创建依赖,对象一般默认单例模式

      递归创建依赖会遇到循环依赖问题:

      • 如果需要的依赖正处于创建状态,则发生了循环依赖(可用ConcurrentHashMap缓存对象来判断)
      • 处理:将那个依赖的初始状态对象注入,即那个依赖对象里的成员变量为null

      BeanFactory简易实现代码:

      public class BeanFactory {
          //一个类对应一个对象
          private static Map<Class<?>, Object> classToBean = new ConcurrentHashMap<>();
      
          public static Object getBean(Class<?> cls) {
              return classToBean.get(cls);
          }
      
          public static void initBean(List<Class<?>> classList) throws Exception {
              List<Class<?>> toCreate = new ArrayList<>(classList);
              while (toCreate.size() != 0) {
                  int remainSize = toCreate.size();
                  for (int i=0;i<toCreate.size();i++) {
                      if (finishCreate(toCreate.get(i))) {
                          toCreate.remove(i);
                      }
                  }
                  if (toCreate.size() == remainSize) {
                      //这里没有解决循环依赖
                      throw new Exception("cycle dependency!");
                  }
              }
          }
      
          private static boolean finishCreate(Class<?> cls) throws IllegalAccessException, InstantiationException {
              if (!cls.isAnnotationPresent(Bean.class) && !cls.isAnnotationPresent(Controller.class)) {
                  return true;
              }
      
              Object bean = cls.newInstance();
              for (Field field : cls.getDeclaredFields()) {
                  if (field.isAnnotationPresent(AutoWired.class)) {
                      Class<?> fieldType = field.getType();
                      Object reliantBean = BeanFactory.getBean(fieldType);
                      if (reliantBean == null) {
                          return false;
                      }
                      field.setAccessible(true);
                      field.set(bean, reliantBean);
                  }
              }
              classToBean.put(cls, bean);
              return true;
          }
      }
      
    六、AOP

    概念:弥补OOP的缺点,给每个函数前后留一个切面,可以实现业务代码和功能代码的分离

    • jdk代理

      被代理对象需要有个接口,jdk通过动态实现这个接口来实现代理

    • cgLib代理

      被代理对象没有接口怎么办?我们通过获取它的class字节码文件,创造一个继承它的子类,从而实现代理

  • 相关阅读:
    c++ const的使用
    C++面向对象程序设计举例
    C++构造函数与析构函数的解析
    inline函数和一般的函数有什么不同
    Linux 脚本为什么会有#!
    Linux 基本概念和操作2
    Linux 基本概念和操作
    ubuntu14.0464位 Ros环境 安装halcon13.01
    数据类型之间的连接和运算
    cmd命令 从C盘转到D盘
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/11070912.html
Copyright © 2011-2022 走看看