首页 > 编程语言 > 详细

Spring IOC

时间:2019-09-22 12:07:36      阅读:71      评论:0      收藏:0      [点我收藏+]

IoC 全称为 Inversion of Control(控制反转),由 Spring IOC 容器来负责对象的生命周期和对象之间的关系
主要依赖源码是 spring-beans 和 spring-context 两个包

依赖注入三种方法

构造器注入:

    被注入的对象通过在其构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。

    YoungMan(BeautifulGirl beautifulGirl){
        this.beautifulGirl = beautifulGirl;
    }

    构造器注入方式比较直观,对象构造完毕后就可以直接使用。

setter 方法注入:

    对于 JavaBean 对象而言,我们一般都是通过 getter 和 setter 方法来访问和设置对象的属性。

    public class YoungMan {
        private BeautifulGirl beautifulGirl;
        public void setBeautifulGirl(BeautifulGirl beautifulGirl) {
            this.beautifulGirl = beautifulGirl;
        }
    }


接口方式注入:

    接口方式注入显得比较霸道,因为它需要被依赖的对象实现不必要的接口,带有侵入性。一般都不推荐这种方式。

启动 Spring 容器

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。

AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置。

技术分享图片

技术分享图片

ClassPathXmlApplicationContext 源码分析

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

    //如果已经有 ApplicationContext,并需要配置成父子关系
    public ClassPathXmlApplicationContext(ApplicationContext parent) {
        super(parent);
    }

    public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent) throws BeansException {
        super(parent);
        Assert.notNull(paths, "Path array must not be null");
        Assert.notNull(clazz, "Class argument must not be null");
        this.configResources = new Resource[paths.length];
        for(int i = 0; i < paths.length; ++i) {
            this.configResources[i] = new ClassPathResource(paths[i], clazz);
        }
        this.refresh();    //核心方法
    }
}


public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    /**
     * 初始化容器
     */
    public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {

            //准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符。
            this.prepareRefresh();

            /**
             * 配置文件解析成一个个 Bean 定义,注册到 BeanFactory 中。
             * Bean还没有初始化,只是配置信息都提取出来了。
             */
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

            //设置 BeanFactory 的类加载器,添加几个BeanPostProcessor,手动注册几个特殊的bean
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);

                //初始化当前 ApplicationContext 的 MessageSource,国际化
                this.initMessageSource();
                this.initApplicationEventMulticaster();

                //典型的模板方法(钩子方法),
                //具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
                this.onRefresh();
                this.registerListeners();

                //初始化所有的 singleton beans(lazy-init 的除外)
                this.finishBeanFactoryInitialization(beanFactory);

                //最后,广播事件,ApplicationContext初始化完成
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                //销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源。
                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

    /**
     * 创建 Bean 容器前的准备工作
     */
    protected void prepareRefresh() {
        //记录启动时间
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
        if (this.logger.isDebugEnabled()) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Refreshing " + this);
            } else {
                this.logger.debug("Refreshing " + this.getDisplayName());
            }
        }

        this.initPropertySources();
        this.getEnvironment().validateRequiredProperties();    //校验 xml 配置文件
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet(this.applicationListeners);
        } else {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        this.earlyApplicationEvents = new LinkedHashSet();
    }


    /**
     * 创建 Bean 容器,加载并注册 Bean,这里将会初始化 BeanFactory、加载 Bean、注册 Bean,Bean 并没有完成初始化
     */
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

        this.refreshBeanFactory();    //关闭旧的 BeanFactory,创建新的 BeanFactory
        return this.getBeanFactory();    //返回刚刚创建的 BeanFactory
    }


    /**
     * 创建 Bean 容器,加载并注册 Bean,这里将会初始化 BeanFactory、加载 Bean、注册 Bean,Bean 并没有完成初始化
     */
    protected final void refreshBeanFactory() throws BeansException {
        if (this.hasBeanFactory()) {

            this.destroyBeans();    //如果 ApplicationContext 中已经加载过 BeanFactory,销毁所有 Bean
            this.closeBeanFactory();    //关闭 BeanFactory
        }

        try {
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();    //初始化BeanFactory实现类

            beanFactory.setSerializationId(this.getId());    //序列化

            this.customizeBeanFactory(beanFactory);    //设置 BeanFactory 的两个配置属性:是否允许 BeanDefinition 覆盖、是否允许循环引用

            //BeanDefinition 中保存了 Bean 信息
            //比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean
            //初始化 Bean 容器:配置文件的配置信息转换为一个个 BeanDefinition,然后注册各个 BeanDefinition 到 BeanFactory。
            this.loadBeanDefinitions(beanFactory);

            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }
}

Spring IOC

原文:https://www.cnblogs.com/loveer/p/11566625.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!