spring总是有一种神奇的魔力,让人想要去探究他到底是做了什么.
提前搭建好工程

- 不要选择Spring Initializr, 那是使用SpringBoot的,不利于学习使用.
 
一路下一步, 填写项目名称, finish.
可以看到,在项目目录下的lib中,IDEA会帮我们把包导好.
直接开始代码
启动类放置的位置是按照SpringBoot的习惯,实际放在哪里都可以.
// Hello类中的代码
public class Hello {
    private String message = "";
    public String getMessage(){
        return message;
    }
    public void setMessage(String message){
        this.message = message;
    }
    public Hello(){}
    public Hello(String message){
        this.message = message;
    }
}
// HelloConfig类中的代码
@Configuration
@ComponentScan(basePackages = "com.echi.demo")
public class HelloConfig {
    @Bean
    public Hello hello(){
        return new Hello("hello world");
    }
}
// 主启动类的代码
public class MainClass {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloConfig.class);
        Hello hello = (Hello)applicationContext.getBean("hello");
        System.out.println(hello.getMessage());
    }
}因为是学习,所以没有加入SpringMvc中关于父子容器,路径拦截的配置, 简简单单创建一个容器将bean放进去再取出来就好了.
开始调试
因为是要看看spring是获取bean的,所以直接将断点打在getBean()这行.
从下面将spring中的代码贴上来
spring代码好看的一点就是,名字都很长, 可以做到见名知意
bean没有标注@Lazy
    // 类名 AbstractApplicationContext
    @Override
    public Object getBean(String name) throws BeansException {
        // 看看这个beanFactory是不是还活着
        // 如果已经死亡抛出一个IllegalStateException 
        assertBeanFactoryActive();
        // 根据名称去获取bean
        return getBeanFactory().getBean(name);
    }
    // 类名 AbstractBeanFactory
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        // 这句和返回值没关系可以不看, 是处理bean的名称的. 
        // bean可以拥有别名,也可能是由factoryBean导致的名称干扰
        final String beanName = transformedBeanName(name);
        Object bean;
        // Eagerly check singleton cache for manually registered singletons.
        // 这句已经有注释, 是 直接去单例缓存池中获取bean.
        // 因为我们没有配置懒加载,所以这边会获取到bean
        // 返回值就是我们在config中配置的Hello对象
        Object sharedInstance = getSingleton(beanName); 
        if (sharedInstance != null && args == null) {
            // 省略部分是一些log
            ...
            // 此处是做一些判断,因为bean已经取出来了.但是取出来的有可能是factoryBean
            // 如果是factoryBean,是不能直接用的,还要通过factoryBean来获取bean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        else {
            // 这部分代码是没取到时的处理,稍后再展开
            ...
        }
        // Check if required type matches the type of the actual bean instance.
        // 做最后的检查
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            // 检查代码省略
            ...
        }
        // 已经获取到bean, 也已经做过检查, 确认没问题了 将bean返回
        return (T) bean;
    }
在上面这段代码可以看到,成功获取到bean.
但是只有get()的动作,那什么时候放进去的呢?
既然在getBean()的时候没有看到在哪里放进去,那断点就往前打一句
    // 类名 AnnotationConfigApplicationContext
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        // 做一些初始化的工作
        // 在这里初始化了
        // - beanFactory
        // - AnnotatedBeanDefinitionReader
        // - ClassPathBeanDefinitionScanner
        this();
        register(annotatedClasses);
        // 主要内容在这个方法内
        refresh();
    }
    // 类名 AbstractApplicationContext
    // 这个方法里全是调用,调用链很深,就不深入进去了.
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 省略部分代码
            ...
            try {
                ...
                // 在这一个方法内,将Hello类的BeanDefinition装入beanDefinitionMap中.
                invokeBeanFactoryPostProcessors(beanFactory);
                ...
                // 在这个方法内将Hello类装入到单例缓存池中.
                finishBeanFactoryInitialization(beanFactory);
                ...
            }
            catch (BeansException ex) {
                // 省略不必要的代码
                ...
            }
            finally {
                ...
            }
        }
    }
    // 类名 AbstractApplicationContext
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 省略代码
        ...
        // 调用了beanFactory的方法将类装载进单例缓存池
        beanFactory.preInstantiateSingletons();
    }
    // 类名 DefaultListableBeanFactory
    @Override
    public void preInstantiateSingletons() throws BeansException {
        ...
        // 获取bean定义的名称
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
        // 循环去挨个实例化
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 如果是factoryBean, 有factoryBean的实例化方式
                if (isFactoryBean(beanName)) {
                    // 使用factoryBean的方式创建bean
                    ...
                }
                // 如果是单纯的bean,直接走上面getBean时省略的步骤.
                // 在getBean()中会创建bean
                else {
                    getBean(beanName);
                }
            }
        }
        for (String beanName : beanNames) {
            // 调用bean初始化后的回调
            ...
        }
    }仔细看一下getBean中创建bean的方式
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        final String beanName = transformedBeanName(name);
        Object bean;
        // 因此这里讨论的是使用该方法创建bean,所以单例缓存池中应该是没有缓存该bean的.
        Object sharedInstance = getSingleton(beanName); // 返回null
        if (sharedInstance != null && args == null) {
            // 不讨论此处
            ...
        }
        else {
            // 在单例缓存池中没有找到bean, 进入该判断分支
            // 判断是否有依赖循环的情况
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            // 看看有没有父容器,是不是在父容器中已经有该bean
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 没有父容器, 此处不讨论
                ...
            }
            if (!typeCheckOnly) {
                // 将该bean标记为已创建, 防止多线程竞争时创建多次. 内部使用的是双重检查
                markBeanAsCreated(beanName);
            }
            try {
                // 开始创建bean的流程
                // 先获取beanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
                // 检查该bean有没有依赖其他bean, 如果有需要将依赖的bean先解决
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 解决依赖bean
                    ...
                }
                // 正式开始创建bean
                // 如果是单例bean,进入该分支
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                // 再内部就是一堆很深的调用,不再深入.
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                // 创建prototype的bean进入该分支
                // prototype就是每次获取都是一个全新的bean
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    // 如果不是单例也不是原型模式, 说明是其他的 request ,session和global session
                    // 这几种scope都是和web请求相关的
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            ...
        }
        return (T) bean;
    }bean标注@Lazy的情况
@Lazy表示懒加载,只有在使用的情况才会去加载.
在上面的例子中,bean的创建是在ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloConfig.class);这一行执行时创建的,在getBean()时直接可以取到.
加了@Lazy注解之后,bean的创建的在getBean()的时候去创建并放入单例缓存池中的.