Spring的IOC初始化流程

xiaoxiao2021-02-28  94

目录

1、理解IOC/DI/DL

1.1、IOC -(Inversion Of Control)

1.2、DL-(Dependency looking )

1.3、DI-(Dependency injection )

2、Spring容器启动流程

3、Spring容器启动源码分析

4、小结


前言 Spring的出现就是为了更好的管理Bean,而IOC/DI/DL又是Spirng的核心,IOC在Spring中可以简单的理解为一个Map容器,帮我们管理控制着Bean的生命周期。 IOC -Inversion of control:控制反转,不是什么技术,而是一种设计思想,把对象的使用和创建分开了。

1、理解IOC/DI/DL

一切从Bean开始,IOC其实就是对我们的Bean进行管理;例如Bean加载,实例化,注册和管理。 例如,拿我们的SpringMVC为例,spring MVC本质上就是一个servlet,遵循了servlet的规范;在启动tomcat的时候,init()方法会完成以下工作: 第一步:JVM会扫描我们的jar或者war包,读取加载配置class文件,进行环境等变量的准备配置; 第二步:继续扫描业务字节码文件,包括相关的类,注解等class文件的全路径; 第三步:把第二步扫描出来的类通过反射进行实例化instance,然后注册到 IOC容器Map中; 第四步:完成 依赖查找注入DL 和 DI,实例化之后bean与bean之间的关系;例如加了@Resource @Autowire等注解的变量关系; 第五步:完成HandlerMapping的初始化,将加了@Controller和@RequestMapping的注解的url和method关系缓存到Map容器中; 第六步:容器启动完成,可以使用; 其中的3-4-5步骤都是在进行IOC的实现,将bean交给Spring容器托管。   继续理解什么是IOC/ID/DL,通过一段经常见的小代码来简单解释分析一下: 常见的Bean配置类: @Configuration //配置类 public class AutowiredPersonConfig {         @Bean     public Person person(){         return new Person();     } }

功能代码实现的:IOC ,依赖注入和依赖查找。

@SpringBootApplication public class SpringBootMainApp {     @Resource //DI 依赖注入     private Person person;     public static void main(String[] args) {                 //IOC,所谓的控制反转,容器载入类,将Bean实例化,然后交给spring容器Map托管;         ApplicationContext app = new AnnotationConfigApplicationContext(AutowiredPersonConfig.class);            //DL 依赖查找,在容器中查找id=person的Bean实例对象;         Person person = (Person) app.getBean("person");         // TODO HERE     } }

分析:容器启动载入类AnnotaionConfigApplicationContext完成Bean的装载和注册,@Resource里面就简单的实现了bean的依赖查找和注入。

1.1、IOC -(Inversion Of Control)

    IOC-控制反转, 简单理解就是一个大的Map集合,主要用来存放Bean对象,new Person();  根据容器载入类来加载Bean对象;     Spring的IOC有很多的Map容器。例如上面的代码,当服务在启动的时候,JVM会扫描我们的jar包,找到class文件中的配置类AutowiredPersonConfig.class,然后将相关加了@Configuratio和@Bean注解的实例Bean Person加入到容器map中,实际等价于做了如下操作: private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); singletonObjects.put("person",new Person());

没有IOC之前,我们要使用对象的时候就需要自己先创建一个对象,自己控制对象的生产,获取相应的资源,另外每次产生一个对象就会往JVM内存中写入一些数据,占用了内存,也增加垃圾回收的行能消耗;

但是有了IOC之后,管理和控制就发生了反转: 控制了什么?对象的new创建和生命周期,相关的依赖资源获取; 反转给谁?管理权反转给Spring,由Spring的 ioc容器来控制Bean生命周期; 这个简单的过程其实就是IOC的过程,  

1.2、DL-(Dependency looking )

DI-依赖查找。完成了Bean的加载,实例化和注册后,当我们要使用的时候,也就是依赖查找与注入的过程: @Resource //DI&DL 依赖查找&注入 private Person person;

实际上等价于执行了下面代码:

第一步:判断是否加了相关的注解信息: 先判断如果变量加了@Resource注解 if (field.isAnnotationPresent(Resource.class)) {     //todo 进行属性赋值; }

第二步:完成DL-依赖查找,从容器map中获取实例Bean Person:

Person person = singletonObjects.get("person");

1.3、DI-(Dependency injection )

第三步:完成DI-依赖注入,通过反射将第一步从容器map中取到的person值设置到 private Person person; 这个变量中。 从MAP容器中获取Person对应的bean实例,并注入到变量person中,完成依赖注入: field.setAccessible(true); field.set(personInstance, person));

其实这也就是完成了person实例变量的依赖查找和注入过程。

2、Spring容器启动流程

下面来看一下Spring容器启动的主要流程: ioc容器的初始化与Bean的创建 第一步: refresh,容器刷新启动的时候,读取扫描jar/war包中的启动类配置文件bean.xml,载入类和application.properties文件; 第二步: 实例化BeanFactory这个Spring的最顶层的容器接口,创建完beanFactory,Spring就有了生产和获取getBean()的能力;另外,BeanFactory还提供一些后置处理器来保证我们的单实例非懒加载的业务bean正确创建;声明顶层map容器,初始化BeanFactory,使容器有getBean的能力; 第三步: finishBeanFactoryInitialization,对剩下的非懒加载单实例业务Bean进行实例化,继续扫描我们的jar或者war包,class文件,得到加了@Controller/@Component/@Service/@Repository等注解的所有要实例化的Bean的全路径名beanDefinationName; 第四步:通过BeanName开始从缓存也就是ioc容器map中直接获取bean实例:通过getBean()-doGetBean() ->getSingleton("beanName") —> map.getBean ("beanName"),先看IOC容器map缓存中是否有我们的singletonBean,有就 直接return,流程结束; 如果map缓存中没已实例化的Bean,则进行创建 第一步:创建对象 createBean (),拿到class类对象,通过反射得到构造函数, 创建对象,new Person(); 第二步:属性赋值 populateBean():person. setName("king") 第三步:执行初始化方法 initializeBean ,代理对象通过applyBeanPostProcessorsBeforeInitializatio n和applyBeanPostProcessorsAfterInitialization进行增强bean的初始化前后增强 至此,bean的创建完成,将单实例bean注册到ioc容器map中; finishRefresh();Spring发送容器事件消息,我启动完成了,你可以做事情了;

3、Spring容器启动源码分析

下面通过源码具体分析一下Spring容器启动的主流程,从容器刷新开始: public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {    this();    register(annotatedClasses);    refresh(); //统一入口 } refresh() 刷新开始: @Override //容器刷新入口: public void refresh() throws BeansException, IllegalStateException {     //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识    synchronized (this.startupShutdownMonitor) {       // Prepare this context for refreshing.       prepareRefresh();       // Tell the subclass to refresh the internal bean factory.       //1、告诉子类启动refreshBeanFactory()方法,实例化创建BeanFactory,用来获取和创建Bean;       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();       // Prepare the bean factory for use in this context.       //为BeanFactory配置容器特性,例如类加载器、事件处理器等       prepareBeanFactory(beanFactory);       try {          // Allows post-processing of the bean factory in context subclasses.          postProcessBeanFactory(beanFactory);          // Invoke factory processors registered as beans in the context.          invokeBeanFactoryPostProcessors(beanFactory);          // Register bean processors that intercept bean creation.          //aop相关bean的创建          //为BeanFactory注册BeanPost事件处理器.和业务bean执行的时机不一样而已,其他都一样;          //BeanPostProcessor是Bean后置处理器的创建,用于监听容器触发的事件          registerBeanPostProcessors(beanFactory);          // Check for listener beans and register them.          registerListeners();          // Instantiate all remaining (non-lazy-init) singletons.          //2、初始化所有剩余的非懒加载的单实例 — 业务Bean—也就是java中写的Bean文件;          finishBeanFactoryInitialization(beanFactory);          // Last step: publish corresponding event.          //容器创建完成,为什么是finish,因为spring中有很多的事件监听机制,告诉监听者我启动完了,你可以做一些事情了;          finishRefresh();       }

开始创建非懒加载的单实例业务Bean:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {    // Initialize conversion service for this context.    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&          beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {       beanFactory.setConversionService(             beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));    }    // Stop using the temporary ClassLoader for type matching.    beanFactory.setTempClassLoader(null);    // Allow for caching all bean definition metadata, not expecting further changes.    beanFactory.freezeConfiguration();    // Instantiate all remaining (non-lazy-init) singletons.    //实例化所有剩下的非懒加载单实例业务Bean    beanFactory.preInstantiateSingletons(); }

得到所有需要实例化的单实例Bean的全路径名,bean信息的定义 -用来生成这个bean的,然后挨个循环实例化:

@Override public void preInstantiateSingletons() throws BeansException {     String FACTORY_BEAN_PREFIX = "&";    //得到所有的需要实例化的Bean的名字    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);    // Trigger initialization of all non-lazy singleton beans…     //挨个循环获取或者创建这个beanName;    for (String beanName : beanNames) {       RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);       if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {          if (isFactoryBean(beanName)) {             Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);             if (bean instanceof FactoryBean) {                final FactoryBean<?> factory = (FactoryBean<?>) bean;                boolean isEagerInit;                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {                   isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)                               ((SmartFactoryBean<?>) factory)::isEagerInit,                         getAccessControlContext());                }                else {                   isEagerInit = (factory instanceof SmartFactoryBean &&                         ((SmartFactoryBean<?>) factory).isEagerInit());                }                if (isEagerInit) {                   getBean(beanName);                }             }          }          else {//获取或者创建这个bean             getBean(beanName);          }       }    }

在创建一个bean之前,先到ioc容器map中去获取相关的bean,如果该bean已经创建,则直接获取返回,不再创建,如果容器map中没有,则进行创建。这也是单例的体现,只创建一次,每次获取的对象都是同一个,可以验证打印它的地址是相同的。

@Override //获取bean信息 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {    return doGetBean(name, requiredType, null, false); } 继续获取bean: protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,       @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {    final String beanName = transformedBeanName(name);    Object bean;     //将bean标记为已创建     if (!typeCheckOnly) {        markBeanAsCreated(beanName);     }    // Eagerly check singleton cache for manually registered singletons.     //通过bean的名字到我们的 IOC大map-其实就是一个缓存 中获取 bean;    Object sharedInstance = getSingleton(beanName);     //如果缓存中有这个bean,则直接返回;     if (sharedInstance != null && args == null) {        if (logger.isTraceEnabled()) {           if (isSingletonCurrentlyInCreation(beanName)) {              logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +                    "' that is not fully initialized yet - a consequence of a circular reference");           }           else {              logger.trace("Returning cached instance of singleton bean '" + beanName + "'");           }        }        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);     }     //如果缓存中没有这个bean,则直接开始创建这个bean;     else {     if (mbd.isSingleton()) {        sharedInstance = getSingleton(beanName, () -> {           try {              return createBean(beanName, mbd, args);           }

从缓存容器map中获取bean单实例;

//private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); protected Object getSingleton(String beanName, boolean allowEarlyReference) {     //直接在map中get    Object singletonObject = this.singletonObjects.get(beanName);    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {       synchronized (this.singletonObjects) { //同步获取;          singletonObject = this.earlySingletonObjects.get(beanName);          if (singletonObject == null && allowEarlyReference) {             ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);             if (singletonFactory != null) {                singletonObject = singletonFactory.getObject();                this.earlySingletonObjects.put(beanName, singletonObject);                this.singletonFactories.remove(beanName);             }          }       }    }     //如果容器中有bean,则直接返回;    return singletonObject; }

如果容器中有这个单实例bean则直接返回创建的流程结束;如果缓存中还没有我们需要的实例Bean,这时候就会开始创建我们的Bean实例:

创建createBean实例的具体步骤: 第一步:通过反射创建对象,new Person(); 第二步:属性赋值;person.set("king") 第三步:执行Bean初始化方法,对于动态代理的对象Bean进行init前后拦截增强; 具体实现如下: @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)       throws BeanCreationException {      try {         // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.         //给个机会返回一个代理对象,这里什么都没做,因为aop的bean是普通的bean的创建过程;        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);        if (bean != null) {           return bean;        }     }    // Make sure bean class is actually resolved at this point, and    // clone the bean definition in case of a dynamically resolved Class    // which cannot be stored in the shared merged bean definition.    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);     try {         //开始创建        Object beanInstance = doCreateBean(beanName, mbdToUse, args);        if (logger.isTraceEnabled()) {           logger.trace("Finished creating instance of bean '" + beanName + "'");        }        return beanInstance; }

创建bean,这里已经有内存地址了,也就是完成了对象的实例化:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)       throws BeanCreationException {    // Instantiate the bean.    BeanWrapper instanceWrapper = null;    if (mbd.isSingleton()) {       instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);    }    if (instanceWrapper == null) {        //这里bean先创建对象,已经有内存地址;相当于Person person = new Person();       instanceWrapper = createBeanInstance(beanName, mbd, args);    }

Spring是通过反射来创建对象,通过createBeanInstance()发现具体创建对象步骤如下:

@Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {    // Don't override the class with CGLIB if no overrides.    if (!bd.hasMethodOverrides()) {       Constructor<?> constructorToUse;       synchronized (bd.constructorArgumentLock) {          constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;                     //反射获取构造函数                   constructorToUse = clazz.getDeclaredConstructor();             }             catch (Throwable ex) {                throw new BeanInstantiationException(clazz, "No default constructor found", ex);             }          }     }         //第一步:反射创建实例完成 等价于Person person = new Person();       return BeanUtils.instantiateClass(constructorToUse);    }     Object exposedObject = bean;     try {         //第二步:属性的赋值和初始化,等价于 person.setName("king");        populateBean(beanName, mbd, instanceWrapper);         //第三步:bean的初始化        exposedObject = initializeBean(beanName, exposedObject, mbd);     }

initializedBean主要是对bean完成一些初始化工作,比如在做动态代理的时候,这里就用到了,对当前的Bean初始化执行前和执行后做一些增强的处理工作,   

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {     if (System.getSecurityManager() != null) {        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {           invokeAwareMethods(beanName, bean);           return null;        }, getAccessControlContext());     }    else {//对bean的初始化       invokeAwareMethods(beanName, bean);    }     Object wrappedBean = bean;    if (mbd == null || !mbd.isSynthetic()) {         //对bean出世化的前置处理器       wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);    }    try {       invokeInitMethods(beanName, wrappedBean, mbd);    }    catch (Throwable ex) {       throw new BeanCreationException(             (mbd != null ? mbd.getResourceDescription() : null),             beanName, "Invocation of init method failed", ex);    }    if (mbd == null || !mbd.isSynthetic()) {         //对bean初始化的后置处理器       wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);    }    return wrappedBean; }

至此,一个业务bean的实例化就完成了,结束之后,将这个bean放入到我们的IOC容器map中去,供后期业务 DI/DL使用;

 

4、小结

        IOC的主要任务就是创建对象Bean,同时通过DL和DI处理Bean之间的关联关系,创建的这些单例对象,所有线程共享,一次创建,到处使用。集中管理,统一分配,减少内存开销。       水滴石穿,积少成多。学习笔记,内容简单,用于复习,梳理巩固。   参考资料: 源码下砸: https://github.com/spring-projects/spring-framework https://spring.io/projects/spring-framework#learn                                    
转载请注明原文地址: https://www.6miu.com/read-80907.html

最新回复(0)