栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring源码全解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring源码全解

文章目录
  • 1.容器简介
    • 什么是容器?
    • IOC/DI
  • 2.容器的结构
    • 2.1 BeanFactory
    • 2.2 ApplicationContext
      • 2.2.1 ConfigurableApplicationContext
      • 2.2.2 WebApplicationContext
  • 3、ApplicationContext 启动流程
    • 3.1、prepareRefresh
    • 3.2、obtainFreshBeanFactory
    • 3.3、prepareBeanFactory
    • 3.4、prepareBeanFactory
    • 3.5、invokeBeanFactoryPostProcessors
    • 3.6-3.8、 initMessageSource、initApplicationEventMulticaster、onRefresh
    • 3.9、registerListeners
    • 3.10、finishBeanFactoryInitialization
    • 3.11、 finishRefresh
  • 4、Spring中的钩子接口
    • 4.1、Aware 接口
    • 4.2、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
    • 4.3、@import、importSelector、importBeanDefinitionRegistrar
    • 3.4、InstantiationAwareBeanPostProcessor
    • 3.5、SmartInstantiationAwareBeanPostProcessor
    • 3.6、MergedBeanDefinitionPostProcessor
  • 5、AOP的原理分析
    • 5.1、基本概念
    • 5.2、主要逻辑

1.容器简介 什么是容器?

Java应用中,对象与对象之间往往存在各种复杂的依赖,对象的构建也会变得越来越复杂,如果这些对象的生命周期全部由开发人员编写的话,那么工作量将会变得无比巨大,对象的管理也会非常复杂。所以才会诞生容器的概念,容器的核心左右只有一个:Bean的管理,当我们需要使用某个 Bean 时,容器会自动帮我们创建,并在适当时销毁。外界有一个标准的名词,前者称呼为 IOC,也就是控制反转,后者称呼为 DI,也就是依赖注入。

IOC/DI
  • IOC (Inversion of Control) 控制反转:

    所谓控制反转,就是当我们需要某个 Bean 时,将 Bean 的名称告知容器,由容器去创建该 Bean,而不是我们手动 new 一个,这里 Bean 创建管理的控制权都交给了容器,所以这是一种控制权的反转。其通俗点讲就是需要什么东西让别人送过来,而不是自己去拿。

  • DI (Dependency Injection) 依赖注入:

    就是指当 A 里面需创建 B 时,会在创建 A的时候,自动将依赖的 B 注入进去,其 B 是被动接受注入而不是自己主动去找。换句话说就是指 A 不是从容器中查找它依赖的 B ,而是容器创建在A 的时候主动将它依赖的 B 注入给它。

2.容器的结构

容器本质上可以也可以看作是 Bean 工厂,该工厂管理 Bean 的生命周期,以及 Bean 之间的依赖关系。外界也将 Spring 容器称为 IOC 容器。当然,这里容器仅仅是 Spring 的抽象概念,代码中将其具象化为 BeanFactory 或 ApplicationContext,容器功能也由具象化的类进行处理。

2.1 BeanFactory

BeanFactory 是容器最基础的类,它定义了容器的基本功能规范:

public interface BeanFactory {

    // 对 FactoryBean 的转义定义,因为如果使用 bean 的名字检索 FactoryBean 得到的对象是工厂生成的对象,
    String FACTORY_BEAN_PREFIX = "&";
    
    // 根据 bean 的名字,获取在容器中 bean 实例
    Object getBean(String name) throws BeansException;
    
    //根据 bean 的名字和 Class 类型来得到 bean 实例,增加了类型安全验证机制。
     T getBean(String name, @Nullable Class requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
     T getBean(Class requiredType) throws BeansException;
     T getBean(Class requiredType, Object... args) throws BeansException;
    
    // 提供对 bean 的检索,看看是否在容器有这个名字的 bean
    boolean containsBean(String name);
    
    // 根据 bean 名字,判断这个 bean 是不是单例
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    
    // 根据 bean 名字,判断这个 bean 是不是原型
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    
    // 根据 bean 名字,判断是否与指定的类型匹配
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, @Nullable Class typeToMatch) throws NoSuchBeanDefinitionException;
    
    // 得到 bean 实例的 Class 类型
    Class getType(String name) throws NoSuchBeanDefinitionException;
    
    // 得到bean 的别名,如果根据别名检索,那么其原名也会被检索出来
    String[] getAliases(String name);
}

在 BeanFactory 里只对容器的基本行为作了定义,其根本不关心你的 Bean 是如何定义怎样加载的。至于工厂是怎么生产这些对象的,这个基本的接口不关心。而要知道工厂是如何产生对象的,我们就需要看具体的容器了,也就是 BeanFactory 的子类。
BeanFactory 大致的继承关系如下:

BeanFactory 体系中常用的实现类有:

  • ListableBeanFactory:提供容器中 bean 迭代的功能。如返回所有 Bean 的名字、容器中 Bean 的数量等。
  • HierarchicalBeanFactory:提供父容器的访问功能,可通过 ConfigurableBeanFactory 的setParentBeanFactory 方法设置父容器。
  • AutowireCapableBeanFactory:为 Spring 容器之外的 Bean ,也就是未交由 Spring 管理的 Bean ,提供依赖注入的功能。

以上三个是 BeanFactory 的直系亲属,这个三个直系亲属下面又派生了两个复杂的容器:

  • ConfigurableBeanFactory:其继承了 HierarchicalBeanFactory 和SingletonBeanRegistry 这两个接口,其提供了很多方法,如:定义类加载器、类型转化、属性编辑器、注册依赖 Bean、销毁 bean 等,且该接口被大多数的容器继承、实现。
  • ConfigurableListableBeanFactory:这个接口继承了 ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory,自身主要提供用于分析和修改 bean定义以及预先实例化单例 Bean 的方法。 最后是核心容器:

DefaultListableBeanFactory:它实现了以上所有的接口,在 BeanFactory 体系中可以作为一个独立的容器使用。

2.2 ApplicationContext

上面说过 ApplicationContext 是 BeanFactory 子类,它不仅包含 BeanFactory 所有功能,还对其进行了扩展,而我们喜欢将 ApplicationContext 称为应用上下文,因为容器只是它的基本功能。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

	// 返回此应用程序上下文的唯一ID
	@Nullable
	String getId();

	// 返回此上下文所属的应用程序名称
	String getApplicationName();

	// 返回应用上下文具像化的类名
	String getDisplayName();

	// 返回第一次加载此上下文时的时间戳
	long getStartupDate();

	// 获取父级应用上下文
	@Nullable
	ApplicationContext getParent();

	// 将 AutowireCapableBeanFactory 接口暴露给外部使用
	AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

ApplicationContext 自身提供的方法非常简单,但它继承了六个接口,来扩展自身功能:

  • EnvironmentCapable:获取 Environment。
  • ListableBeanFactory、HierarchicalBeanFactory:这是 BeanFactory 体系接口,分别提供 Bean 迭代和访问父容器的功能。
  • MessageSource:支持国际化功能。
  • ApplicationEventPublisher:应用事件发布器,封装事件发布功能的接口。
  • ResourcePatternResolver:该接口继承至 ResourceLoader ,作用是加载多个 Resource。
  • ApplicationContext 同样提供了非常多的实现类,其又可细分为两大类,ConfigurableApplicationContext 和 WebApplicationContext。
2.2.1 ConfigurableApplicationContext

该接口是比较重要的一个接口,几乎所有的应用上下文都实现了该接口。该接口在ApplicationContext的基础上提供了配置应用上下文的能力,此外提供了生命周期的控制能力。

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {

	// 应用上下文配置时,这些符号用于分割多个配置路径
	String CONFIG_LOCATION_DELIMITERS = ",; tn";

	// BeanFactory中,ConversionService类所对应的bean的名字。如果没有此类的实例的话吗,则使用默认的转换规则
	String CONVERSION_SERVICE_BEAN_NAME = "conversionService";

	//LoadTimeWaver类所对应的Bean在容器中的名字。如果提供了该实例,上下文会使用临时的 ClassLoader ,这样,LoadTimeWaver就可以使用bean确切的类型了 
	String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";

	// Environment 类在容器中实例的名字
	String ENVIRONMENT_BEAN_NAME = "environment";

	// System 系统变量在容器中对应的Bean的名字
	String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";

	// System 环境变量在容器中对应的Bean的名字
	String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";

    // 设置容器的唯一ID
	void setId(String id);

	// 设置此容器的父容器
	void setParent(@Nullable ApplicationContext parent);

	// 设置容器的 Environment 变量
	void setEnvironment(ConfigurableEnvironment environment);

	// 以 ConfigurableEnvironment 的形式返回此容器的环境变量。以使用户更好的进行配置
	@Override
	ConfigurableEnvironment getEnvironment();

	// 此方法一般在读取应用上下文配置的时候调用,用以向此容器中增加BeanFactoryPostProcessor。增加的Processor会在容器refresh的时候使用。
	void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);

	// 向容器增加一个 ApplicationListener,增加的 Listener 用于发布上下文事件,如 refresh 和 shutdown 等
	void addApplicationListener(ApplicationListener listener);

	// 向容器中注入给定的 Protocol resolver
	void addProtocolResolver(ProtocolResolver resolver);

	// 这是初始化方法,因此如果调用此方法失败的情况下,要将其已经创建的 Bean 销毁。
    // 换句话说,调用此方法以后,要么所有的Bean都实例化好了,要么就一个都没有实例化
	void refresh() throws BeansException, IllegalStateException;

	// 向JVM注册一个回调函数,用以在JVM关闭时,销毁此应用上下文
	void registerShutdownHook();

	// 关闭此应用上下文,释放其所占有的所有资源和锁。并销毁其所有创建好的 singleton Beans
	@Override
	void close();

	// 检测此 FactoryBean 是否被启动过
	boolean isActive();

	// 返回此应用上下文的容器。
	// 千万不要使用此方法来对 BeanFactory 生成的 Bean 做后置处理,因为单例 Bean 在此之前已经生成。
    // 这种情况下应该使用 BeanFactoryPostProcessor 来在 Bean 生成之前对其进行处理
	ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

该接口下又有几个重要的实现类:

  • AbstractApplicationContext:这是个抽象类,仅实现了公共的上下文特性。这个抽象类使用了模板方法设计模式,需要具体的实现类去实现这些抽象的方法。
  • GenericApplicationContext:该类继承自 AbstractApplicationContext,是为通用目的设计的,它能加载各种配置文件,例如 xml,properties 等等。它的内部持有一个 DefaultListableBeanFactory 的实例,实现了
  • BeanDefinitionRegistry 接口,以便允许向其应用任何 bean 的定义的读取器。
  • AnnotationConfigApplicationContext:该类继承自 GenericApplicationContext,提供了注解配置(例如:@Configuration、@Component等)和类路径扫描(scan方法)的支持。
2.2.2 WebApplicationContext

该接口是专门为 Web 应用准备的,其允许从相对于 Web 根目录的路径中装载配置文件完成初始化。

public interface WebApplicationContext extends ApplicationContext {

	// 整个 Web 应用上下文是作为属性放置在 ServletContext 中的,该常量就是应用上下文在 ServletContext 属性列表中的 key
	String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

	// 定义了三个作用域的名称
	String SCOPE_REQUEST = "request";
	String SCOPE_SESSION = "session";
	String SCOPE_APPLICATION = "application";

	// 在工厂中的 bean 名称
	String SERVLET_CONTEXT_BEAN_NAME = "servletContext";

	// ServletContext 初始化参数名称
	String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";

	// 在工厂中 ServletContext 属性值环境bean的名称
	String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";

	// 用来获取 ServletContext 对象
	@Nullable
	ServletContext getServletContext();
}

该接口的核心实现类有:

  • ConfigurableWebApplicationContext:该接口同时继承了 WebApplicationContext 和 ConfigurableApplicationContext,提供了 Web 应用上下文的可配置的能力。
  • GenericWebApplicationContext:该类继承自 GenericApplicationContext,实现了
    ConfigurableWebApplicationContext。
  • XmlWebApplicationContext:该上下文是使用 Xml 配置文件的方式,不过是在 Web 环境中使用的。
  • AnnotationConfigServletWebServerApplicationContext:该类是被 SpringBoot扩展而来的,SpringBoot 使用的就是该上下文。
3、ApplicationContext 启动流程
  • 1、从启动类开始
@Xiao7Application(appName = "example", port = "8081", env = AppConstant.ENV_DEV)
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class SpringbootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootDemoApplication.class, args);
    }
}

  • 2、SpringApplication的run方法
public ConfigurableApplicationContext run(String... args) {
    
    ...
    
    ConfigurableApplicationContext context = null;
    
    ...
    
    try {
        ...
        // 通过 createApplicationContext 方法创建上下文,根据 Web 环境不同创建的上下文也不同
        context = createApplicationContext();
    
        ...
        // 该方法用于启动上下文
        refreshContext(context);
        ...
    
    }
    catch (Throwable ex) {
        ...
    }
    
    context = createApplicationContext();
    
    ...
}
  • 3、AbstractApplicationContext的refresh方法
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 初始化 refresh 的上下文环境,就是记录下容器的启动时间、标记已启动状态、处理配置文件中的占位符
        prepareRefresh();

        // 2. 初始化 BeanFactory,加载并解析配置,会添加一些必要的Processor
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

        // 3. 对 BeanFactory 进行功能增强,如设置BeanFactory的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
        prepareBeanFactory(beanFactory);

        try {
            // 4. 后置处理 beanFactory,交由子类实现
            postProcessBeanFactory(beanFactory);

            // 5. 调用已注册的 BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册 BeanPostProcessor,仅仅是注册,调用在getBean的时候。
            // 6.1、同时添加了一个ApplicationListenerDetector
            registerBeanPostProcessors(beanFactory);

            // 7. 初始化国际化资源
            initMessageSource();

            // 8. 初始化事件广播器
            initApplicationEventMulticaster();

            // 9. 留给子类实现的模板方法
            onRefresh();

            // 10. 注册事件监听器
            registerListeners();

            // 11. 实例化所有非延迟加载的单例
            finishBeanFactoryInitialization(beanFactory);

            // 12. 完成刷新过程,发布应用事件
            finishRefresh();
            
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
            }
            
            // 13.销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
            this.destroyBeans();
            
            // Reset 'active' flag.
            this.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...
            this.resetCommonCaches();
        }
    }
}

逐一分析:

3.1、prepareRefresh

初始化 refresh 的上下文环境,就是记录下容器的启动时间、标记已启动状态、处理配置文件中的占位符

3.2、obtainFreshBeanFactory

这一步就是创建一个DefaultListableBeanFactory,并进行初步的初始化,将需要的组件注册进容器。这里还会有一步加载的操作:loadBeanDefinitions(beanFactory);

主要有两步操作:

  1. 使用ClassPathBeanDefinitionScanner去扫描指定包中的Bean,默认创建的Scanner只会注册Component、ManagedBean、Named这三种注解的Bean
  2. 如果includeAnnotationConfig属性为true的话会注册一些支持注解、事件的处理器,比如:ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory等。
3.3、prepareBeanFactory

对 BeanFactory 进行功能增强,如设置BeanFactory的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean,添加一个ApplicationListenerDetector时间派发器。

3.4、prepareBeanFactory

一个钩子方法,提供给子类扩展。

3.5、invokeBeanFactoryPostProcessors

调用已注册的 BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor,其中BeanDefinitionRegistryPostProcessor 继承了BeanFactoryPostProcessor接口。

这里会先执行BeanDefinitionRegistryPostProcessor,然后在执行BeanFactoryPostProcessor。并且会根据PriorityOrdered、Ordered优先级进行排序控制执行顺序。

两个接口的区别:

BeanDefinitionRegistryPostProcessor:使用BeanDefinitionRegistry,可以进行Bean的注册删除操作。

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

BeanFactoryPostProcessor:使用ConfigurableListableBeanFactory,可以进行Bean的创建删除操作。

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

在3.2中创建了ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor,这两个后置处理器很关键。

  • ConfigurationClassPostProcessor:解析@Configuration、importSelector、importBeanDefinitionRegistrar、@import @PropertySource、@importResource等接口和注解。并将解析的Bean注册进容器中去。
  • AutowiredAnnotationBeanPostProcessor:实现了InstantiationAwareBeanPostProcessor在对象填充属性的时候会解析@Autowired注解并inject填充至对象属性中。
3.6-3.8、 initMessageSource、initApplicationEventMulticaster、onRefresh

初始化国际化资源、初始化事件广播器、容器刷新的钩子函数。

3.9、registerListeners

注册事件监听器:就是从已注册的Bean中找出实现ApplicationListener接口的Bean添加进ApplicationEventMulticaster中,如果有earlyApplicationEvents容器事件的话,进行时间的派发。

3.10、finishBeanFactoryInitialization

这一步应该是整个容器刷新最重要的一步了。创建还没实例化的非懒加载的Bean。

这一步只是创建还没实例化的Bean,并不是说所所有Bean的创建都在这里。Bean的创建可以在Factory创建好之后的任何地方实例化。

以下是需要注意的要点:

  1. doCreateBean之前会给Bean一下提前创建的机会,通过InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法实现。

  2. createBeanInstance使用构造方法实例化对象时会回调SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法寻找构造函数创建对象。没有才会使用默认构造函数。

  3. 创建完实例后会执行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition后置处理。

  4. 这时候有一步操作是用于借据循环依赖的问题。放入一个FactoryBean到三级缓存中,到时候获取对象会执行SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法获取代理对象,从而实现对代理对象循环依赖的支持。这里如果只是循环依赖的话二级缓存也是足够的。

  5. populateBean填充属性,填充之前会调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation后置处理。

    这一步会获取对象的PropertyValues属性值对象,会调用InstantiationAwareBeanPostProcessor的postProcessProperties对属性对象扩展处理。

    找对对应的属性对象后会执行操作,applyPropertyValues这里有一步操作是使用BeanDefinitionValueResolver解析值,因为注入的属性可能是对象而不是基础类型。比如如果是RuntimeBeanReference对象则会去容器中获取到。最后通过反射将对象的属性设置进去。

  6. initializeBean初始化对象,到了这一步,其实对象已经创建好了,只是进行一些额外的初始化操作。

    invokeAwareMethods:设置aware对象(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)

    执行BeanPostProcessor的postProcessBeforeInitialization初始化前置处理方法。
    invokeInitMethods(beanName, wrappedBean, mbd):执行自定义的初始化方法,然后执行初始化后置处理器方法。像Aop的代理对象也就是在这一步去创建的,也有可能是getEarlyBeanReference方法中创建的。

    对象的创建到这里也已经完成了。

3.11、 finishRefresh

完成刷新过程,发布应用事件。

4、Spring中的钩子接口 4.1、Aware 接口

Aware 从字面意思理解就是知道、感知的意思,是用来获取 Spring 内部对象的接口。Aware 自身是一个顶级接口,它有一系列子接口,在一个 Bean 中实现这些子接口并重写里面的 set 方法后,Spring 容器启动时,就会回调该 set 方法,而相应的对象会通过方法参数传递进去。

  • BeanFactoryAware:获取 BeanFactory 对象,它是基础的容器接口。
  • ApplicationContextAware:获取Content
  • BeanNameAware:获取 Bean 的名称。
  • EnvironmentAware:获取 Environment 对象,它表示整个的运行时环境,可以设置和获取配置属性。
  • ApplicationEventPublisherAware:获取 ApplicationEventPublisher对象,它是用来发布事件的。
  • ResourceLoaderAware:获取 ResourceLoader 对象,它是获取资源的工具。
4.2、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor 是 Bean 工厂的后置处理器,一般用来修改上下文中的 BeanDefinition,修改 Bean 的属性值。

BeanDefinitionRegistryPostProcessor是 BeanDefinitionRegistry 的后置处理器,一般用来扩展Bean的注册。

4.3、@import、importSelector、importBeanDefinitionRegistrar

importSelector 是一个较为重要的扩展接口,通过该接口可动态的返回需要被容器管理的类,不过一般用来返回外部的配置类。可在标注 @Configuration 注解的类中,通过 @import 导入 importSelector 来使用。

importBeanDefinitionRegistrar和 importSelector 类似,也是配合 @import 使用,不过 importBeanDefinitionRegistrar 更为直接一点,它可以直接把 Bean 注册到容器中。

它们是在ConfigurationClassPostProcessor中扩展实现的,也是Spring启动是会自动注册的几个处理器之一。

3.4、InstantiationAwareBeanPostProcessor

它是BeanPostProcessor的子接口。

调用时机:

  1. 对象创建前调一次,给机会提前创建。postProcessBeforeInstantiation
  2. 填充属性前调用一次。postProcessAfterInstantiation
  3. 填充属性时调一次。postProcessProperties
3.5、SmartInstantiationAwareBeanPostProcessor

它是InstantiationAwareBeanPostProcessor的子接口。

  1. predictBeanType:断言这个Bean的所属类型。
  2. determineCandidateConstructors:获取对象的构造方法
  3. getEarlyBeanReference:提供代理扩展的,获取对象的早起引用对象。
3.6、MergedBeanDefinitionPostProcessor

它是BeanPostProcessor的子接口。

  • postProcessMergedBeanDefinition:它会在对象实例化但是没填充属性值之前回调一次。
  • resetBeanDefinition:removeBeanDefinition时的回调通知方法做一些缓存数据的变更之类的。
5、AOP的原理分析

了解Aop前需要了解java中代理的方式有哪一些:

Java代理博客:https://www.cnblogs.com/cenyu/p/6289209.html

5.1、基本概念

在Spring AOP中,代理对象执行的过程通常被称为通知,而通知者由三部分组成:

  1. Pointcut(切点):可以把它看成匹配器,就是用来匹配某个类的某个方法的。

    public interface Pointcut {
    	// 类过滤器
    	ClassFilter getClassFilter();
    	// 方法的匹配器
    	MethodMatcher getMethodMatcher();
    	// 默认的切点,总是匹配
    	Pointcut TRUE = TruePointcut.INSTANCE;
    }
    
  2. Advice(通知):具体的通知方法,常用的就是MethodInterceptor (方法的拦截器)就是你要实现的切面执行的代码要放的地方。

    // MethodInterceptor 也是继承Advice 的
    public interface MethodInterceptor extends Interceptor,Advice {
    	// MethodInvocation就是具体的方法执行器,调用invocation.proceed()执行
    	Object invoke(MethodInvocation invocation) throws Throwable;
    }
    
  3. Advisor(通知者):可以把它看成 Advice(通知) 和 Pointcut(切点)的集成管理者。

    public class Xiao7Advisor implements PointcutAdvisor{
        @Override
        public Pointcut getPointcut() {
            return new Xiao7Point();
        }
    
        @Override
        public Advice getAdvice() {
            return new Xiao7Interceptor();
        }
    
        @Override
        public boolean isPerInstance() {
            return true;
        }
    }
    
5.2、主要逻辑

主要的实现逻辑是在AbstractAutoProxyCreator中,先看一下它的集成继承机构结构。
可以看到它本身是实现了SmartInstantiationAwareBeanPostProcessor、BeanPostProcessor、InstantiationAwareBeanPostProcessor三个后置处理器的。

主要作用的实现接口有三个:

  1. getEarlyBeanReference:获取早期引用的,前面说Spring创建对象的时候,会将ObjectFactory放入缓存中,最终调用的时候也是执行到这一步的。

    	@Override
    	public Object getEarlyBeanReference(Object bean, String beanName) {
    		Object cacheKey = getCacheKey(bean.getClass(), beanName);
    		this.earlyProxyReferences.put(cacheKey, bean);
    		return wrapIfNecessary(bean, beanName, cacheKey);
    	}
    
  2. postProcessBeforeInstantiation:Bean开始创建前如果设置了提前暴露,会进来这一步,如果返回了对象就不会走Spring的逻辑创建对象了。

    	@Override
    	public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {
    		Object cacheKey = getCacheKey(beanClass, beanName);
    
    		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    			if (this.advisedBeans.containsKey(cacheKey)) {
    				return null;
    			}
    			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    				this.advisedBeans.put(cacheKey, Boolean.FALSE);
    				return null;
    			}
    		}
    
    		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    		if (targetSource != null) {
    			if (StringUtils.hasLength(beanName)) {
    				this.targetSourcedBeans.add(beanName);
    			}
    			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
    			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    			this.proxyTypes.put(cacheKey, proxy.getClass());
    			return proxy;
    		}
    
    		return null;
    	}
    
  3. postProcessAfterInitialization:初始化对象后执行方法,Aop的代理对象基本都是在这一步去创建的

    	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的具体的逻辑

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 1、会判断是否支持和跳过
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// getAdvicesAndAdvisorsForBean  是去获取这个Bean支持的对应的通知者
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 这一笔就是去创建代理对象了
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

其中getAdvicesAndAdvisorsForBean的主要逻辑是从已注册的对象中找出Advisor,并且进行一次匹配,需要注意的是只要类和某一个方法匹配成功了就属于合格的Advisor了。

找到的Advisor之后就是去创建代理对象了。
先会创建一个ProxyFactory(代理工厂),把代理需要的对象放进去,然后把对象的通知也放进去。

protected Object createProxy(Class beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		// 包装一下,同时需要做一下适配扩展
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

从proxyFactory.getProxy(getProxyClassLoader())追述下去会到DefaultAopProxyFactory中创建代理。


最终会根据接口的有无,是否配置代理目标类等判断使用Jdk代理还是cglib代理,这里构造具体的代理工厂使用的AdvisedSupport就是上一步包装了advisors 和目标类的proxyFactory。

这里的话只看下jdk代理的逻辑。JdkDynamicAopProxy中的主要源码:

	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		// 获取advised中的代理接口
		Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 创建代理对象,其中InvocationHandler就是当前对象,也就是JdkDynamicAopProxy
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

JdkDynamicAopProxy.invoke的主要代码如下:

// 会先从advisors中获取到满足这个方法的advice也就是具体的每一个拦截器
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 为空的话走原逻辑
if (chain.isEmpty()) {
	Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
	retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
	// 需要创建一个方法执行器,把代理对象、参数、目标类、拦截器链传进去,然后执行
	MethodInvocation invocation =
			new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
	retVal = invocation.proceed();
}
 

ReflectiveMethodInvocation中的proceed执行流程

public Object proceed() throws Throwable {
	// currentInterceptorIndex默认是-1,
	// 当它等于interceptorsAndDynamicMethodMatchers.size() - 1的时候就说明已经执行完了。
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}

	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	// 可以自定义一个动态方法匹配,一直到这一步才会判断之后需要过滤这个方法
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			return proceed();
		}
	}
	else {
		// MethodInterceptor调用,执行完一个后又会回来这个方法,一直到执行整个链路都执行完了。
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

这里的interceptorsAndDynamicMethodMatchers就是真正需要执行的拦截器链了。

  • 如果advice实现了InterceptorAndDynamicMethodMatcher接口的话,在这里还会做一下最终的匹配。过了才会执行它。
  • 这里MethodInterceptor,invoke(this)会一直递归循环,一直到满足(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1)的时候才会执行原对象的具体方法。
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号