手写Sping(2) :手写IOP与DI(依赖注入)

为了方便理解项目中的实现,我们先对IOC与DI进行简单的介绍

控制反转

IoC(Inverse of Control:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。所谓IOC一句话搞定:对象由Spring来创建、管理、装配。而DI(依赖注入)是实现IOC的一种方式。所谓的控制反转就是获取依赖对象的方式反转了。
在这里插入图片描述
Spring IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。 IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。

控制翻转怎么理解:举个例子,"对象a 依赖了对象 b,当对象 a 需要使用 对象 b的时候必须自己去创建。但是当系统引入了 IOC 容器后, 对象a 和对象 b 之前就失去了直接的联系。这个时候,当对象 a 需要使用 对象 b的时候, 我们可以指定 IOC 容器去创建一个对象b注入到对象 a 中"。对象a获得依赖对象b的过程由主动行为变为了被动行为,控制权翻转,这就是控制反转名字的由来。

核心代码实现

在下面的代码中,createBeanDefinitionMap是为了创建Bean名与BeanDefinition相对应的映射关系,BeanDefinition将包含该Bean的相关信息,如bean的类、bean是单例还是原型、bean是否需要被代理。
BeanDefinition的存在将有助于我们实现bean的创建。

根据前文我们对于IOC的介绍,可以知道,IOC本质上是一个容器,项目在初始化后,这个容器将包含一些项目中需要的Bean,这些bean有的是单例,有的是原型。对于单例bean,我们需要时就直接从单例池中取出,对于原型bean,我们在需要使用时直接创建即可,这部分在下文代码的 getBean() 部分。在创建bean时,我们要对bean中被@Autowired的字段进行注入,这是依赖注入过程,这部分在下文代码的 doCreateBean() 部分。

public class BeanHelper {
    private static String aspectPath="com.luban.demo.controller";
    private static  Map<String,BeanDefinition> beanDefinitionMap=new HashMap<String, BeanDefinition>();
    //单例池
    public static  Map<String,Object> singletonObjects=new HashMap<String, Object>();
    private static Map<Class<?>,Object> aopMap;

    static {
    	// 创建BeanDefinitionMap
        createBeanDefinitionMap();
        //初始化
        AopHelper aopHelper=new AopHelper();
        aopMap=aopHelper.getProxyMap();
        
        instanceSingletonBean();
    }
    
    public static void createBeanDefinitionMap(){
        Set<Class<?>> classSet=new ClassHelper().getAllClass();
        //将所有beanDefinition实例化并放入容器
        for (Class<?> beanClass:classSet) {
            if (beanClass.isAnnotationPresent(Component.class)) {
                Component componentAnnotation = beanClass.getAnnotation(Component.class);
                String beanName = componentAnnotation.value();
                BeanDefinition beanDefinition = new BeanDefinition();
                beanDefinition.setBeanClass(beanClass);
                beanDefinition.setAspect(beanClass.getName().startsWith(aspectPath));
                //如果clazz是被Scope注解的类
                if (beanClass.isAnnotationPresent(Scope.class)) {
                    //获取clazz上Scope的注解信息,获取bean的作用范围Scope
                    Scope scopeAnnotation = beanClass.getAnnotation(Scope.class);
                    beanDefinition.setScope(scopeAnnotation.value());
                } else {
                    //单例
                    beanDefinition.setScope("singleton");
                }
                beanDefinitionMap.put(beanName, beanDefinition);
            }else if (beanClass.isAnnotationPresent(Service.class)){
                Service componentAnnotation = beanClass.getAnnotation(Service.class);
                String beanName = componentAnnotation.value();
                BeanDefinition beanDefinition = new BeanDefinition();
                beanDefinition.setBeanClass(beanClass);
                beanDefinition.setAspect(beanClass.getName().startsWith(aspectPath));
                //如果clazz是被Scope注解的类
                if (beanClass.isAnnotationPresent(Scope.class)) {
                    //获取clazz上Scope的注解信息,获取bean的作用范围Scope
                    Scope scopeAnnotation = beanClass.getAnnotation(Scope.class);
                    beanDefinition.setScope(scopeAnnotation.value());
                } else {
                    //单例
                    beanDefinition.setScope("singleton");
                }
                beanDefinitionMap.put(beanName, beanDefinition);
            }
        }
    }
    
    public static void instanceSingletonBean() {
        for (String beanName:beanDefinitionMap.keySet()){
            BeanDefinition beanDefinition= (BeanDefinition) beanDefinitionMap.get(beanName);
            //如果是单例bean,需要存入单例池
            if (beanDefinition.getScope().equals("singleton")){
                //创建bean,对于被AOP的类,直接加强放入到singletonObjects的map中
                if (!singletonObjects.containsKey(beanName)){
                    Object bean=doCreateBean(beanName,beanDefinition);
                    singletonObjects.put(beanName,bean);
                }
            }
        }
    }

    private static Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
        //实例化,利用java的反射机制完成
        try {
            //1.实例化
            Class<?> beanClass=beanDefinition.getBeanClass();
            Object instance;
            //实例化bean
            instance=beanClass.getDeclaredConstructor().newInstance();
            //2.属性填充/依赖注入
            //Field即字段即类中的成员变量
            //getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
            //getDeclaredFields()获得某个类的所有声明的字段,即包括public、private和proteced
            Field[] fields=beanClass.getDeclaredFields();
            for (Field field:fields){
                //如果该字段采用Autowired注入
                if (field.isAnnotationPresent(AutoWired.class)){
                    String fieldName=field.getName();
                    Object o=getBean(fieldName);
                    //开启field的set模式
                    field.setAccessible(true);
                    //将bean的field字段设置为o
                    field.set(instance,o);
                }
            }
            
            //3.回调,设置beanName
            if (instance instanceof BeanNameAWare){
                ((BeanNameAWare)instance).setBeanName(beanName);
            }
            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Object getBean(String beanName){
        // beanName 单例的,原型的
        BeanDefinition beanDefinition= beanDefinitionMap.get(beanName);
        Object bean=null;
        if (beanDefinition.getScope().equals("prototype")){
            //如果是原型bean,创建一个新的
            bean=doCreateBean(beanName,beanDefinition);
        }else if (beanDefinition.getScope().equals("singleton")){
            //否则,从单例池中加载
            bean=singletonObjects.get(beanName);
            if (bean==null){
                Object bean1=doCreateBean(beanName,beanDefinition);
                singletonObjects.put(beanName,bean1);
                return bean1;
            }
        }
        return bean;
    }

    public static void setBeanPraoxy(Class<?> targetClass, Object proxy) {
        String name = null;
        for (Map.Entry<String,BeanDefinition> entry:beanDefinitionMap.entrySet()){
            BeanDefinition beanDefinition=entry.getValue();
            if (beanDefinition.getBeanClass().equals(targetClass)){
                name=entry.getKey();
                break;
            }
        }
        singletonObjects.put(name,proxy);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值