【Spring系列】- 手写模拟Spring框架( 三 )


// 1.7 在通过这个clazz(类)来判断是否有component注解,有则是beanif (clazz.isAnnotationPresent(Component.class)) { Component annotation = clazz.getAnnotation(Component.class); String beanName = annotation.value();    // * 默认生成bean,如果只使用Component注解,没有写上beanName的值,那么就需要自动生成    if (beanName.equals("")) {        // 默认开头小字母        beanName = Introspector.decapitalize(clazz.getSimpleName());    } /**  * 這就是一个bean了  * 然而在这里并不是直接就创建bean了,bean分为了单例bean和多例bean  */ BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setType(clazz); if (clazz.isAnnotationPresent(Scope.class)) { // 判断是单例还是多例Scope scope = clazz.getAnnotation(Scope.class);beanDefinition.setScope(scope.value()); } else {beanDefinition.setScope("singleton"); }    beanDefinitionMap.put(beanName, beanDefinition);}getBean底层通过传来一个beanName , 通过beanDefinitionMap中获取key为beanName的BeanDefinition对象,进行判空处理 。这样我们可以通过这个BeanDefinition对象去获取作用域,判断是否为单例 。
获取bean在此,我们创建单例的时候,是需要将单例保存起来的,需要定义ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();单例池来保存单例bean 。然后在getBean的时候,如果是单例bean,就可以先去单例池中寻找,如果没找到,再去创建对象 。而多例模式就需要每次都去创建 。
// 获取bean对象public Object getBean(String beanName) {    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);    if (beanDefinition == null) {        throw new NullPointerException("找不到bean名字为[" + beanName + "]的bean对象");    } else { // 找到就做相应的操作        String scope = beanDefinition.getScope();        if (scope.equals("singleton")) {            // 通过单例池获取            Object bean = singletonObjects.get(beanName);            if (bean == null) {                // 单例池中如果没有bean,就需要去创建                bean = createBean(beanName, beanDefinition);                singletonObjects.put(beanName, bean);            }            return bean;        } else {            // 多例的就不需要记录 , 每次都是通过创建            return createBean(beanName, beanDefinition);        }    }}创建bean利用反射机制,通过无参构造方法去获取实例,这里就是bean对象实例了 。就可以直接返回 。
// 创建beanprivate Object createBean(String beanName, BeanDefinition definition) { // 利用反射获取实例 , 采用无参构造方法 Class clazz = definition.getType(); // 通过无参构造方法获取实例 try {Object instance = clazz.getConstructor().newInstance(); // 到这里直接返回,bean的对象也就创建完成return instance; } catch (InstantiationException e) {e.printStackTrace(); } return null;}在构造方法扫描后要根据生成的beanDefinitionMap去创建单例bean对象 。
// 2 创建单例bean对象for (String beanName : beanDefinitionMap.keySet()) {    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);    if (beanDefinition.getScope().equals("singleton")) { // 那么,如何保证单例呢?就需要有个单例池,singletonObjects        Object bean = createBean(beanName, beanDefinition);        singletonObjects.put(beanName, bean); // 将单例bean存到单例池中    }}

推荐阅读