Spring源码学习 + Spring部分面试题

310 阅读9分钟

Spring源码:

反射:

//获取类对象
Class clazz = Class.forName("完全限定名");
Class clazz = 对象.getClass();
Class clazz = 类.class;

//创建实例
clazz.newInstance();
Constructor cons = clazz.getDeclareConstructor();
Object obj = cons.newInstance();

然后会用到BeanFactoryPostProcessor,在BeanFactory中去实例化相关的bean,先进行配置,然后可以使用这个接口去定义它的方法。

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

Spring:

接口——>beanFactory——>实例化bean——>属性注入——>before——>初始化bean(init方法调用)——>after

这里before和after其实就是aop的扩展方法:

看beanPostProcessor接口,有个AbstractAutoProxyCreator类,其中有createProxy方法,里面return了一个getProxy调用后的方法,进去

public Object getProxy(@Nullable ClassLoader classLoader) {
    return this.createAopProxy().getProxy(classLoader);
}

这里调用了createAopProxy,进去,又创建了createAopProxy调用的方法的对象,但这个方法是接口的方法,进入其实现类DefaultAopProxyFactory,这里主要就是最后这一行,cglib和jdk动态代理。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
        return new JdkDynamicAopProxy(config);
    } else {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
        } else {
            return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
        }
    }
}

还是这个AbstractAutoProxyCreator类,里面有

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    return bean;
}

/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

wrapIfNecessary方法中有个createProxy()方法,正好就是上面那个方法,因为它是创建代理的。

上面箭头的位置正好就是bean的生命周期了,如果想进一步了解,那么去beanFactory接口看注释

image-20211008092223175

Enviroment包含两个主要部分env和properties,看接口的StandardEnviroment实现类,获取系统的环境和配置.。

image-20211008093551811
protected void customizePropertySources(MutablePropertySources propertySources) {
    propertySources.addLast(new PropertiesPropertySource("systemProperties", this.getSystemProperties()));
    propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", this.getSystemEnvironment()));
}

想了解Spring源码需要了解refresh方法,在AbstractAppliacationContext。refresh中有17个方法。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        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.
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

先进入prepareRefresh(),里面的getEnvironment方法

getEnvironment().validateRequiredProperties();

这里创建了个环境对象

public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}

第二个方法是obtainFreshBeanFactory,也就是获取beanFactory,点进去有个refreshBeanFactory()方法,再进入它的实现类AbstractRefreshableApplicationContext的refreshBeanFactory方法,如果有工厂就清除重新创建一个;这里要注意DefaultListableBeanFactory方法,然后该配置beanFactory

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

第三个方法prepareBeanFactory,这个时候factory准备完成了,该处理beanFactory的增强信息了,也就是粉色部分,这里最开始的beanFactory赋的都是默认值,现在要填充定义好的属性值。下面这个图只是一个总体功能介绍,不是执行顺序。

image-20211008101848568
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context's class loader etc.
   beanFactory.setBeanClassLoader(getClassLoader());
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // Configure the bean factory with context callbacks.
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   // BeanFactory interface not registered as resolvable type in a plain factory.
   // MessageSource registered (and found for autowiring) as a bean.
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);
}

上面只是这个方法的一小部分,可以看到有set、add、register、ignore等设置。

第四个方法是postProcessBeanFactory,后置处理bean工厂。

第五个方法是invokeBeanFactoryPostProcessors,调用beanFactory的后置处理器,也就是调用粉色的部分。

第六个方法registerBeanPostProcessors,是注册bean processors

第七个方法initMessageSource,进行国际化处理(i18n),也就是页面语言切换

第八个方法initApplicationEventMulticaster,初始化应用程序事件的多播器,用来后面进行事件的监听

第九个方法onRefresh,没什么意义

第十个方法registerListeners,注册监听器,也就是beanFactory完成之前把监听器,监听事件等都准备好

第十一个方法finishBeanFactoryInitialization,实例化所有非懒加载的单例


1、Spring IOC的理解

两个东西:控制反转和容器,控制反转简单说明即可,容器:存储对象用的,使用map结构来存储对象,在spring中一般存在三级缓存,singletonObject存放完整的bean对象。创建到销毁的过程都是由Spring管理

细化:

  • 容器的创建过程(beanFactory、DefaultListableBeanFactory),创建bean工厂,向bean工厂中设置一些参数(BeanPostProcessor,Aware接口的子类)等属性
  • 加载解析bean对象,准备好要创建的bean对象的定义对象beanDefinition(xml,注解解析过程)
  • 开始beanFactoryPostProcessor的处理,这里是扩展点,(PlaceHolderConfigureSupport,ConfigurationClassPostProcessor)
  • beanPostProcessor的注册功能,方便后续对bean对象的扩展功能
  • 通过反射的方式将BeanDefinition对象实例化成具体的bean对象
  • bean对象的初始化过程(DI,调用Aware子类的方法,调用BeanPostProcessor前置处理方法,调用init方法,调用BeanPostProcessor的后置处理方法)
  • 生成完整的bean对象,通过getBean方法可以直接获取到
  • 销毁过程

2、Spring IOC的底层实现

反射 + 工厂

createBeanFactory,getBean,doGetBean,createBean,doCreateBean,createBeanInstance,populateBean。

  • 先通过createBeanFactory创建一个beanFactory(DefaultListableBeanFactory)
  • 开始循环创建对象,容器中的bean默认是单例,所以优先通过getBean,doGetBean从容器中查找,
  • 如果找不到的画,通过createBean,doCreateBean方法以反射的方式创建对象,一般情况下使用的是无参构造方法(getDeclaredConstructor、newInstance)创建
  • 进行对象的属性填充populateBean
  • 进行其他的初始化操作(initializingBean)

3、bean的生命周期

image-20210607103405031
  • 实例化:反射的方式生成对象
  • 填充属性bean:熟悉可以谈谈populateBean,循环依赖问题(三级缓存)
  • 调用aware接口方法:invokeAwareMethod(完成BeanName,BeanFactory,BeanClassLoader对象的属性设置)
  • 调用BeanPostProcessor的前置处理方法:使用比较多的由ApplicationContextPostProcessor,设置ApplicationContext,Enviroment,ResourceLoader等对象
  • 调用init-method方法:invokeInitmethod()方法,判断是否实现了InitializeingBean接口,如果由调用AfterPropertiesSet方法,没有不调用
  • 调用BeanPostProcessor的后置处理方法:使用比较多的Spring aop就是在这里实现的,AbstractAutoProxyCreator就是干这个用的
  • 获取到完整的bean,可通过getBean获取对象
  • 销毁:判断是否实现了DispoableBean接口,调用destroyMethod方法

4、Spring的循环依赖如何解决?

关键点:三级缓存;提前暴露对象;aop

A依赖B,B依赖A,不断依赖下去;

bean的创建过程是这样的:实例化---初始化(填充属性)

  • 先创建A对象,实例化A对象,此时A对象b属性为null,从容器中查找B对象,找到了就赋值,找不到就创建B对象
  • 实例化B对象,填充B对象的属性,从容器中查找A对象,找不到创建A对象
  • 这里就闭环导致循环依赖的

5、缓存的放置时间和删除时间

三级缓存:createBeanInstance之后放置,addSingletonFactory()方法

二级缓存:第一次从三级缓存确定对象是代理对象还是普通对象的时候,同时删除三级缓存,getSingleton()

一级缓存:将完整对象生成后,放入一级缓存,删除二三级缓存,addSingleton()

6、BeanFactory和FactoryBean有什么区别?

相同点:都是用来创建bean对象的

不同点:当使用beanFactory创建对象的时候必须遵循严格的生命周期流程,比较复杂,如果想要自定义某个对象的创建,同时创建完成的对象交给spring管理,就需要实现FactoryBean接口(BeanFactory是复杂版创建,FactoryBean是简化版创建)

  • isSingleton:是否是单例
  • getObjectType:获取返回对象的类型
  • getObject:自定义创建对象的过程(new、反射、动态代理)

7、常用的设计模式

单例模式、原型模式、工厂模式、模板方法模式(postProcessBeanFactory,onRefresh,initPropertyValue,))、策略模式(xmlBeanDefinitionReader、PropertiesBeanDefinition)、观察者模式(listener、event、multicart)、适配器模式(Adapter)、装饰者模式(BeanWrapper)、责任链模式(使用aop的时候会先生成一个拦截器链)、代理模式(动态代理)、委托者模式(delegate)

8、aop底层实现原理

aop是ioc的一个扩展功能

bean的创建过程中有个步骤可以对bean进行扩展实现,aop本身就是个扩展功能,所以在BeanPostProcessor的后置处理器中来实现

  • 代理对象的创建过程(advice、切面、在哪些方法上进行扩展)
  • 通过jdk或cglib的方式来生成代理对象
  • 在执行方法调用的时候,会调用生成的字节码文件中,直接会找到DynamicAdvisoredInterceptor类的intercept方法,从此方法开始执行
  • 根据之前定义好的通知来生成拦截器链
  • 从拦截器链中依次获取每一个通知开始进行执行,执行过程中为了方便找到下一个通知是哪个,会有一个InvocationInterceptor对象,找的时候是从-1的位置开始查找,并且执行的

9、Spring事务是如何回滚的

其实是在问spring事务管理是怎么实现的?

Spring的事务是由aop来实现的,首先生成具体的代理对象,按照aop的整套流程完成具体的逻辑操作,一般是这样,但是aop中事务不是通过通知来实现的,而是通过TransactionInterceptor来实现的,然后调用invoke来实现具体的逻辑。

  • 准备工作,包含具体的操作:解析各个方法上事务相关的属性,根据具体的属性来判断是否开启新事务
  • 当需要开启新事务时,获取数据库连接,关闭自动提交功能,开启事务
  • 执行具体的sql逻辑操作
  • 在操作过程中,如果执行失败了,那么会通过completeTransactionAfterThrowing来完成事务的回滚操作,回滚的具体逻辑是doRollBack方法来实现的,实现的时候也是要先获取连接对象,通过连接对象回滚
  • 如果执行过程中,没有发生意外,通过commitTransactionAfterReturing来完成事务的提交操作,事务的具体逻辑是通过doCommit来实现的,也是先获取连接再提交
  • 当事务执行完毕之后需要清除相关的事务信息cleanupTransactionInfo