手写Spring框架源码(基础款)(Aware回调,初始化,BeanPostProcessor)

在原生Spring框架中,其实框架给了很多在创建Bean之前的一些自定义的回调方法

可以让你自由度更高的自定义创建出来的Bean,比如各种Aware接口以及初始出Bean方法

那咱们也模仿Spring也做同样的事情

第一步:定义Aware或者初始化bean的接口

public interface BeanNameAware {

    public void setBeanName();
}
public interface InitializingBean {

    void afterPropertiesSet();

}

第二步:让自己写的bean实现Aware接口

实现接口,就必然要重写接口方法,比如我们将beanName设置成yu

@Component("yuWenWenService")
public class YuWenWenService implements BeanNameAware {


    @Autowired
    private MiaoWenWenService miaoWenWenService;

    public String beanName;

    @Override
    public void setBeanName() {
        beanName="yu";
    }

    public void test() {
        System.out.println(miaoWenWenService);
        System.out.println(beanName);
    }
}

第三步:在ApplicationContext回调接口方法

在上一篇文章编写代码时,我们已经实装了,根据反射创建对象,以及进行属性的依赖注入

    private Object createBean(BeanDefinition beanDefinition)
        throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 第一步:创建对象
        Object o = beanDefinition.getClazz().getDeclaredConstructor().newInstance();
        // 第二部:依赖注入
        // 先通过反射拿到这个对象的私有属性
        Field[] declaredFields = o.getClass().getDeclaredFields();
        // 遍历私有属性
        for (Field field : declaredFields) {
            // 判断私有属性的是否持有@Autowired
            if (field.isAnnotationPresent(Autowired.class)) {
                // 如果持有@Autowired 就从单例池里拿这个bean并赋值
                Object bean = getBean(field.getName());

                // 默认是不允许设置私有属性的值的 此处必须得改成true
                field.setAccessible(true);
                // 实现依赖注入
                field.set(o, bean);

            }
        }
        // 第三步:Aware回调以及初始化方法
。。。。。。。。。。
        return o;
    }

这次依赖注入完成之后,我们就要进行aware回调和初始化bean

        // 第三步:Aware回调以及初始化方法
        if (o instanceof BeanNameAware){
            ((BeanNameAware) o).setBeanName();
        }
        if (o instanceof InitializingBean){
            ((InitializingBean) o).afterPropertiesSet();
        }

如此一来,一个bean的生命周期已经进行了 创建对象->属性依赖注入->Aware回调->初始化回调

我们来测试一下是否成功回调

public class ApplicationTest {


    public static void main(String[] args)
        throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        YuWenWenApplicationContext yuWenWenApplicationContext = new YuWenWenApplicationContext(AppConfig.class);
        YuWenWenService yuWenWenService = (YuWenWenService) yuWenWenApplicationContext.getBean("yuWenWenService");
        yuWenWenService.test();
    }
}

测试成功,已经成功把beanName赋值给yu了 

com.sbi.service.MiaoWenWenService@7aec35a
yu

 第五步:在原生的Spring框架中,除了Aware,和初始化回调方法

还有一个叫后置处理器(BeanPostProcessor)可以自定义Bean

定义一个BeanPostProcessor的接口(这个接口有两个方法,一个是初始化前,一个是初始化后)

public interface BeanPostProcessor {

    default Object postProcessBeforeInitialization(Object bean) {

        return bean;
    }

    default Object postProcessAfterInitialization(Object bean) {
        return bean;
    }

}

定义自己的BeanPostProcessor去实现这两个方法

@Component("yuWenWenBeanPostProcessor")
public class YuWenWenBeanPostProcessor implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean) {
        System.out.println("后置处理器,初始化前");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean) {
        System.out.println("后置处理器,初始化后");
        return bean;
    }
}

继续编写ApplicationContext的逻辑,在之前的scan方法中加入这段逻辑

//判断是否持有Component注解。。。。。。。

                //扫描@Comptent注解发现有实现BeanPostProcessor的类
                if (BeanPostProcessor.class.isAssignableFrom(aClass)){
                    // 就将此类通过反射创建出来
                    BeanPostProcessor beanPostProcessor = (BeanPostProcessor)aClass.getDeclaredConstructor().newInstance();
                    // 将这个后置处理器加到list里
                    beanPostProcessorList.add(beanPostProcessor);
                }

这样一来就在创建Bean的时候逻辑就变成以下这个样子

        // 第三步:Aware回调以及初始化方法
        if (o instanceof BeanNameAware) {
            ((BeanNameAware) o).setBeanName();
        }

        // 第四步:BeanPostProcessor的前置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            o = beanPostProcessor.postProcessBeforeInitialization(o);

        }
        // 第五步:初始化方法
        if (o instanceof InitializingBean) {
            ((InitializingBean) o).afterPropertiesSet();
        }
        // 第六步:BeanPostProcessor的后置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            o = beanPostProcessor.postProcessAfterInitialization(o);
        }

测试一下:成功

后置处理器,初始化前
后置处理器,初始化后

Aware和初始化回调还是和 BeanPostProcessor的用法上还是有区别

Aware和初始化回调:是指当前类实现接口,对当前Bean进行自定义设置

后置处理器(BeanPostProcessor):是可以对所有的Bean进行改造,当然也可以对某一个进行自定义设置

YuWenWenApplicationContext源码奉上
package com.sbi.config;

import com.sbi.annotation.Autowired;
import com.sbi.annotation.Component;
import com.sbi.annotation.ComponentScan;
import com.sbi.annotation.Scope;
import com.sbi.service.BeanPostProcessor;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class YuWenWenApplicationContext {

    private Class config;

    // 单例池(key:beanName,value:bean)
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    // BeanDefinitionMap(key:beanName,value:类描述)
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    // BeanPostProcessorList
    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public YuWenWenApplicationContext(Class config)
        throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        this.config = config;
        // 扫描bean,并且得到所有beanDefinition放在beanDefinitionMap里
        scan(config);
        // 循环beanDefinitionMap全部
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            if (entry.getValue().getScope().equals("singleton")) {
                // 创建bean
                Object bean = createBean(entry.getValue());
                // 将创建好的bean放到单例池等待getBean调用
                singletonObjects.put(entry.getKey(), bean);
            }
        }
    }

    private Object createBean(BeanDefinition beanDefinition)
        throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 第一步:创建对象
        Object o = beanDefinition.getClazz().getDeclaredConstructor().newInstance();
        // 第二部:依赖注入
        // 先通过反射拿到这个对象的私有属性
        Field[] declaredFields = o.getClass().getDeclaredFields();
        // 遍历私有属性
        for (Field field : declaredFields) {
            // 判断私有属性的是否持有@Autowired
            if (field.isAnnotationPresent(Autowired.class)) {
                // 如果持有@Autowired 就从单例池里拿这个bean并赋值
                Object bean = getBean(field.getName());

                // 默认是不允许设置私有属性的值的 此处必须得改成true
                field.setAccessible(true);
                // 实现依赖注入
                field.set(o, bean);

            }
        }
        // 第三步:Aware回调以及初始化方法
        if (o instanceof BeanNameAware) {
            ((BeanNameAware) o).setBeanName();
        }

        // 第四步:BeanPostProcessor的前置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            o = beanPostProcessor.postProcessBeforeInitialization(o);

        }
        // 第五步:初始化方法
        if (o instanceof InitializingBean) {
            ((InitializingBean) o).afterPropertiesSet();
        }
        // 第六步:BeanPostProcessor的后置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            o = beanPostProcessor.postProcessAfterInitialization(o);
        }
        return o;
    }

    private void scan(Class config)
        throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 此处得到@ComponentScan的扫描路径
        ComponentScan path = (ComponentScan) config.getDeclaredAnnotation(ComponentScan.class);
        // 得到一个类加载器 classpath下面用AppClassLoader
        ClassLoader classLoader = YuWenWenApplicationContext.class.getClassLoader();
        // 得到类的包路径(此处为com.sbi.service格式需要改成com/sbi/service)
        URL resource = classLoader.getResource(path.value().replace(".", "/"));
        // 得到包下的文件
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            // 得到包下所有的文件信息
            File[] files = file.listFiles();
            for (File f : files) {
                String absolutePath = f.getAbsolutePath();
                String pathReplaceBefore = absolutePath
                    .substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                String pathreplaceAfter = pathReplaceBefore.replace("\\", ".");
                // 此处最终需要com.sbi.service.YuWenWenService格式
                Class<?> aClass = classLoader.loadClass(pathreplaceAfter);

                // 如果这个类拥有@Component注解,那么我们就要反射
                if (aClass.isAnnotationPresent(Component.class)) {
                    //扫描@Comptent注解发现有实现BeanPostProcessor的类
                    if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                        // 就将此类通过反射创建出来
                        BeanPostProcessor beanPostProcessor = (BeanPostProcessor) aClass.getDeclaredConstructor()
                            .newInstance();
                        // 将这个后置处理器加到list里
                        beanPostProcessorList.add(beanPostProcessor);
                    }
                    Component declaredAnnotation = aClass.getDeclaredAnnotation(Component.class);
                    // 拿到@Component的value值也就是bean的名字
                    String springbeanName = declaredAnnotation.value();
                    // 描述类创建
                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(aClass);
                    // 判断这个类是否还持有@Scope的其他作用域(spring 一共有四种作用域,默认不指定的情况下就是单例)
                    if (aClass.isAnnotationPresent(Scope.class)) {
                        Scope declaredAnnotation1 = aClass.getDeclaredAnnotation(Scope.class);
                        beanDefinition.setScope(declaredAnnotation1.value());
                    } else {
                        // spring默认不指定的情况下就是单例作用域
                        beanDefinition.setScope("singleton");
                    }
                    // 将类信息放到beanDefinitionMap里
                    beanDefinitionMap.put(springbeanName, beanDefinition);
                }

            }
        }
    }

    public Object getBean(String beanName)
        throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        //去beanDefinitionMap寻找是否有自己的类描述
        if (beanDefinitionMap.containsKey(beanName)) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            //如果是单例bean,直接从单例池拿
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = singletonObjects.get(beanName);
                return bean;
                //如果是原型bean就给创建一个新的bean
            } else {
                Object bean = createBean(beanDefinition);
                return bean;
            }
            //没招到的情况下就说明此类并没有加@Competent
        } else {
            throw new NullPointerException("此类不存在");
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值