1.【Spring源码】- 02 Spring IoC容器启动之refresh方法
2.Spring注解驱动开发二狗子让我给他讲讲@EnableAspectJAutoProxy注解
【Spring源码】- 02 Spring IoC容器启动之refresh方法
在注册阶段,注g注AnnotationConfigApplicationContext构造方法中的解源解源第一个方法被分析过。接下来,码s码解我们关注第二个方法:register(componentClasses)。注g注在使用XML配置方式时,解源解源通过new ClassPathXmlApplicationContext("classpath:spring.xml")来创建实例,码s码解android源码设计模式分析其中需要指定xml配置文件路径。注g注使用注解方式时,解源解源也需要为ApplicationContext提供起始配置源头,码s码解这里使用配置类代替xml配置文件,注g注按照配置类中的解源解源注解(如@ComponentScan、@Import、码s码解@Bean)解析并注入Bean到IoC容器。注g注
通过配置类,解源解源Spring解析注解实现Bean的码s码解elipse关联源码注入。使用@Configuration注解定义的配置类相当于xml配置文件,但目前Spring推荐使用注解方式,xml配置的使用概率正在降低。
register(componentClasses)方法的核心逻辑在AnnotatedBeanDefinitionReader#doRegisterBean中,将传入的配置类解析为BeanDefinition并注册到IoC容器。ConfigurationClassPostProcessor这个BeanFactory后置处理器在IoC初始化时,获取配置类的BeanDefinition集合,开始解析。
真正启动IoC容器的流程在refresh()方法中,这是了解IoC容器启动流程的关键步骤。refresh方法在AbstractApplicationContext中定义,采用模板模式,提供IoC初始化流程的基本实现,子类可以扩展。源码如何编写
下面分析refresh()方法的每个步骤,以了解IoC容器的启动流程。
prepareRefresh方法主要在refresh执行前进行准备工作,如设置Context的启动时间、状态,以及扩展系统属性相关。
initPropertySources()方法主要用于扩展配置来源,如网络、物理文件、数据库等加载配置信息。StandardEnvironment默认只提供加载系统变量和应用变量的功能,用于子类扩展。
❝initPropertySources方法常见扩展场景包括:❞
getEnvironment().validateRequiredProperties()确保设置的必要属性在环境中存在,否则抛出异常终止应用。Javaapi源码笔记
BeanFactory是Spring的基本IoC容器,ApplicationContext包装了BeanFactory,提供更智能、更便捷的功能。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取的BeanFactory是IoC容器初始化工作的基础。
上面获取的BeanFactory还不能直接使用,需要填充必要的配置信息。至此,IoC容器的启动流程基本完成。
这里对IoC启动流程有个大致、直观的印象。主要步骤包括:准备阶段、配置来源扩展、初始化BeanFactory、天下三源码填充配置、解析配置类、注册Bean、实例化BeanPostProcessor、初始化国际化和事件机制、以及创建内嵌Servlet容器(在SpringBoot中实现)。这些步骤确保了IoC容器顺利启动并管理Bean。
Spring注解驱动开发二狗子让我给他讲讲@EnableAspectJAutoProxy注解
在配置类上添加@EnableAspectJAutoProxy注解,能够开启注解版的AOP功能。这意味着,如果在AOP中要启用注解版的AOP功能,就需要在配置类上添加@EnableAspectJAutoProxy注解。让我们来看看@EnableAspectJAutoProxy注解的源码,如下所示。
从源码可以看出,@EnableAspectJAutoProxy注解使用@Import注解引入了AspectJAutoProxyRegister.class对象。那么,AspectJAutoProxyRegistrar是做什么的呢?我们点击到AspectJAutoProxyRegistrar类的源码中,如下所示。
可以看到AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口。我们回顾ImportBeanDefinitionRegistrar接口的定义,如下所示。
通过ImportBeanDefinitionRegistrar接口,我们可以实现将自定义的组件添加到IOC容器中。也就是说,@EnableAspectJAutoProxy注解使用AspectJAutoProxyRegistrar对象自定义组件,并将相应的组件添加到IOC容器中。
在AspectJAutoProxyRegistrar类的registerBeanDefinitions()方法中设置断点,我们以debug的方法来运行AopTest类的testAop()方法。当程序运行到断点位置时,我们可以看到程序已经暂停,IDEA的左下角显示了方法的调用栈。
在registerBeanDefinitions()方法中,首先调用AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法来注册registry。在registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,直接调用了重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法。在重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,传入了AnnotationAwareAspectJAutoProxyCreator.class对象。
在registerOrEscalateApcAsRequired()方法中,接收到的Class对象的类型为:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator。然后,我们继续跟进代码。
在registerOrEscalateApcAsRequired()方法中,首先判断registry是否包含org.springframework.aop.config.internalAutoProxyCreator类型的bean。接下来,我们继续看代码。
最终,AopConfigUtils类的registerOrEscalateApcAsRequired()方法中,会通过registry调用registerBeanDefinition()方法注册组件,并注册的bean的名称为org.springframework.aop.config.internalAutoProxyCreator。
接下来,我们继续看AspectJAutoProxyRegistrar类的registerBeanDefinitions()源码。我们通过AnnotationConfigUtils类的attributesFor方法来获取@EnableAspectJAutoProxy注解的信息。接下来,我们继续判断proxyTargetClass属性的值是否为true,如果为true则调用AopConfigUtils类的forceAutoProxyCreatorToUseClassProxying()方法;继续判断exposeProxy属性的值是否为true,如果为true则调用AopConfigUtils类的forceAutoProxyCreatorToExposeProxy()方法。
综上所述,向Spring的配置类上添加@EnableAspectJAutoProxy注解后,会向IOC容器中注册AnnotationAwareAspectJAutoProxyCreator。
了解了这些之后,我们就可以关注「冰河技术」微信公众号,后台回复不同的关键字获取相应的PDF文档。这些文档都是由冰河原创并整理的超硬核教程,包括《深入浅出Java 种设计模式》、《Java8新特性教程》和《亿级流量下的分布式限流解决方案》,都是面试必备的资料。
最后,如果你觉得这篇文章对你有帮助,别忘了点个赞,给个在看和转发,让更多的人看到,一起学习,一起进步!