Spring源码分析 关键类介绍 ApplicationContext 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 万能的 applicationContext, 但实际上各种能力都是依赖于其他的类, 比如 getBean 是 beanFactory 的, publishEvent 是事件广播器的, 等等. 其本身是一个综合体, 整合这些能力, 便于开发者调用和理解. ApplicationContext 是一个只读的 bean 容器 可以加载解析配置文件(如xml) 可以发布事件和注册监听 具有国际化消息处理能力 ConfigurableApplicationContext 是一个具有可配置能力的 容器(可设置各个参数, 如id, 父容器) 具有容器生命周期概念, 如启动,停止,关闭. AbstractApplicationContext 模板方法模式的抽象类, 定义了容器的模板(refresh方法), 但由具体的子类实现部分方法 管理Bean和BeanFactory的PostProcessor 管理事件的监听和处理 AbstractRefreshableApplicationContext 为可重复刷新的容器提供基类 加入了BeanFactory的管理(创建/关闭等) AbstractRefreshableConfigApplicationContext 加入了configLocation字段, 用于某些容器初始化BeanFactory和Bean AbstractXmlApplicationContext 定义了读取xml配置文件来加载BeanFactory的代码, 使得子类只需提供配置文件地址或Resource ClassPathXmlApplicationContext 继承基类, 提供配置文件地址的构造方法, 调用refresh加载BeanFactory
BeanFactory 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 1.核心中的核心, 加载和管理 beanDefinitions(Bean配置信息), 创建和管理 bean 对象实例, 注册和管理 BeanPostProcessor(Bean扩展) BeanFactory 定义了 Bean 的基础操作接口, 如 getBean, getType, isSingleton 等 SingletonBeanRegistry 定义了单例对象的操作接口 (注册/获取/是否已存在) HierarchicalBeanFactory 定义了父 BeanFactory 的相关操作接口(获取) ConfigurableBeanFactory 定义了对 BeanFactory 做各种配置的操作接口, 包括 BeanPostProcessor, setParentBeanFactory, destroyBean, registerAlias, resolveAliases 等 DefaultSingletonBeanRegistry 实现了 SingletonBeanRegistry 接口, 即实现了单例对象的缓存管理, 包括一级/二级/三级(二级三级只依赖循环用上的两个缓存) FactoryBeanRegistrySupport 继承了 DefaultSingletonBeanRegistry 实现对使用 FactoryBean 存储和获取 bean 对象实例方式的支持 AbstractBeanFactory 继承了 FactoryBeanRegistrySupport 实现了 BeanFactory/HierarchicalBeanFactory/ConfigurableBeanFactory 定义的接口 实现了具体 getBean, 包括缓存管理等 AutowireCapableBeanFactory 定义了根据 class 类型获取 BeanDefinition 信息以及 Bean 对象的接口 AbstractAutowireCapableBeanFactory 继承自 AbstractBeanFactory 实现了 AutowireCapableBeanFactory 中定义的方法(就是实现了根据 class 获取 bean 或 BeanDefinition) 实现了 createBean, 也就是真正的实例化一个对象的过程, 包括实例化, 为需要赋值的字段注入相应的值 同时触发了 BeanPostProcessor 的方法调用 BeanDefinitionRegistry 定义了 BeanDefinition 的注册/获取/移除 ListableBeanFactory 定义了 BeanDefinition 的可遍历性 ConfigurableListableBeanFactory 结合 ListableBeanFactory 和 ConfigurableBeanFactory 并补充完善了几个相关接口 (如 getBeanNamesIterator 接口 ) DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory 实现了 BeanDefinitionRegistry/ConfigurableListableBeanFactory 的接口 定义处: BeanFactory(getBean) SingletonBeanRegistry(addSingleton) HierarchicalBeanFactory(getParentBeanFactory) ConfigurableBeanFactory(addBeanPostProcessor) AutowireCapableBeanFactory(autowireBean) BeanDefinitionRegistry(registerBeanDefinition) ListableBeanFactory(getBeanDefinitionNames) ConfigurableListableBeanFactory(getBeanNamesIterator) 实现处: DefaultSingletonBeanRegistry(registerSingleton) FactoryBeanRegistrySupport(getObjectFromFactoryBean) AbstractBeanFactory(doGetBean) AbstractAutowireCapableBeanFactory(createBean) DefaultListableBeanFactory(registerBeanDefinition)
容器初始化过程 1 2 3 4 5 6 7 8 9 10 11 12 13 1.setParent(): 处理父容器 2.setConfigLocations(): 解析并设置xml配置文件路径 3.refresh(): 创建 beanFactory 对象并初始化, 读取 xml 配置文件得到 beanDefinitions, 接着处理两种 PostProcessor, 然后添加国际化处理器和事件广播器以及相应的初始化和一些处理, 最后实例化单例的 bean 等等. 1.prepareRefresh(): 准备工作, 一些字段值的设置和处理. 2.obtainFreshBeanFactory(): 创建一个 beanFactory 对象并注册到 applicationContext (即赋值到字段上), 然后解析 xml 配置文件(或注解配置)的信息, 解析得到 beanDefinitions 并注册到容器中. 3.然后是一些对 beanFactory 对象的完善配置的代码 4.扫描并执行 BeanFactoryPostProcessor(其作用是为beanFactory对象添加东西提供扩展性), 其中我认识的就只有 ConfigurationClassPostProcessor(这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan等基础注解). 5.扫描实现了 BeanPostProcessor 接口的 bean 并注册到 beanFactory 中存起来, 等 createBean 创建对象时会在对应的时机执行一些对应的方法(钩子). 常见的各种 XxxAware 就是靠这个实现的咯. 6.接着, 初始化国际化资源处理器, 事件广播器, 并注册一些需要注册的事件(也注册容器内实现对应接口的 bean) 7.处理一些 beanFactory 的配置, 接着为所有单例且非懒加载的(不就是默认策略嘛) bean 创建实例, 缓存起来. 8.广播容器加载完成了的事件. 以及处理生命周期.
最后总结下, 先创建容器, 再将根据配置文件解析得到 BeanDefinition 注册到容器中, 然后处理两大扩展(BeanFactoryPostProcessor/BeanPostProcessor), 接着是Spring的国际化, 以及相当有用的事件广播器, 最后实例化 bean. 整体感觉其实很简单, 但其实有大量的工作交给了 BeanPostProcessor.
超长源码分析过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 Test.java public class Test { public static void main (String[] args) { ApplicationContext xmlContext = new ClassPathXmlApplicationContext("application-wq.xml" ); UserServiceImpl userService = xmlContext.getBean(UserServiceImpl.class ) ; userService.sayHi(); } } application-wq.xml <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default -autowire="byName" > <bean name="userService" class ="cn.gudqs7.spring.tests.UserServiceImpl" > <property name="starter"><ref bean="serverStarter"/></property> </bean> <bean name="serverStarter" class ="cn.gudqs7.spring.tests.ServerStarter" > <property name="userService"><ref bean="userService"/></property> </bean> </beans> UserServiceImpl.java @Service public class UserServiceImpl { @Resource private ServerStarter starter; public void sayHi () { System.out.println(starter); System.out.println("Hello Spring!" ); } public void setStarter (ServerStarter starter) { this .starter = starter; } } ServerStarter.java @Service public class ServerStarter implements ApplicationListener <ContextRefreshedEvent > { @Inject private UserServiceImpl userService; @Override public void onApplicationEvent (ContextRefreshedEvent event) { String applicationName = event.getApplicationContext().getApplicationName(); System.out.println(applicationName); System.out.println(userService); System.out.println("========== started by gudqs7 ==============" ); System.out.println("========== started by gudqs7 ==============" ); System.out.println("========== started by gudqs7 ==============" ); } public void setUserService (UserServiceImpl userService) { this .userService = userService; } }
😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public ClassPathXmlApplicationContext ( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super (parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
我错了, 代码都放上去不如给个GitHub地址, 接下来省略代码吧, 只放注释😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 org.springframework.context.support.AbstractApplicationContext#prepareRefresh org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>) org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext) org.springframework.context.support.AbstractApplicationContext#registerListeners org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization org.springframework.context.support.AbstractApplicationContext#finishRefresh
可算复制完了, 如果你有幸直接跳读到这里, 那么送上地址 : 注意分支吧
另外上面方法前带个 # 的, 复制到 IDEA 双击 Shift 然后粘贴, 选择 Symbols 搜索更准确呢!
获取容器对象过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1.检查 applicationContext 和 beanFactory 的状态, 若有异常则给出准确的错误. 2.扫描容器中所有此 type 的 beanName, 遍历判断每个 beanName 是否可用 可用则判断可用的个数是否刚好是一个, 是则直接调用 getBean() 返回对象实例 若可用的个数超过一个, 则根据 beanDefinition 的 isPrimary 和对比配置的优先级是否为有最高的再返回最高的 若都不行, 则报错. 3.接着看 getBean, 先试着从单例的缓存中获取, 若存在则返回. 4.若缓存中不存在, 则判断父容器是否存, 若存在则从父容器获取 若父容器不存在, 则自己新建, 先标记 beanName 到 alreadyCreated 中(表示已经创建了防止重复创建) 再开始创建一个 bean. 5.创建一个新的 bean 实例, 先处理 beanDefinition 的 dependsOn 属性(即若存在则先调用 getBean 获取依赖的 bean) 6.若 beanDefinition 的设置是单例, 则通过闭包对创建对象前后进行一些异常处理和缓存处理(主要是彻底创建完后加入到单例一级缓存, 移除二级和三级缓存[循环依赖相关的两个缓存]). 7.通过反射根据 beanClass 创建一个对象实例, 然后将其添加到 singletonFactories 中(解决依赖循环问题) 8.调用 populateBean() 为对象的字段(属性)注入它所需要的值(可能是@Resource, @Value等); (此时可能会遇到依赖循环问题, 但解决这个问题的缓存在此之前就添加了, 所以不怕) 9.最后调用 initializeBean() 完成 bean 的初始化(调用 bean 的一些方法, 如 afterPropertiesSet), 返回对象实例.
总结: 先根据 type 找到 beanName, 找到后根据 beanName 创建对象; 创建对象前先检查缓存(单例), 再考虑父容器, 最后才是自己创建, 自己创建会先创建 dependsOn 的 bean 对象, 然后才通过反射实例化出一个对象实例(这里反射用到的class和构造方法, 通过实现 SmartInstantiationAwareBeanPostProcessor接口都可进行干预), 实例化后存到二级缓存, 再为字段赋值(注入); 最后调用 bean 的 init 相关的接口(如afterPropertiesSet), 就可以返回这个对象实例了.
超长源码分析过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 @Override public <T> T getBean (Class<T> requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(requiredType); } org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean) org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean) org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
各种实现的原理 1 2 3 4 5 6 7 1.为何我写的 class 实现一些接口(如ApplicationContextAware)后并放入容器中, 就可以获取到一些对象(如applicationContext)? 2.为何我写的 class 实现 ApplicationListener<XxxEvent> 后并放入容器中, 就能监听我想知道的事件? 3.为何Spring中遇到各种顺序问题, 只需要实现 Ordered 接口(或加上@Order注解)就能使其有序? 4.Spring是如何解决循环依赖的(指用字段注入而非构造方法)? 5.Spring可以用注解替换XML配置文件了, 是如何实现的呢(常用注解的实现原理)? 6.Spring AOP是如何实现的(指@Aspect)? 7.Spring 事务是如何实现的(指@Transaction)?
为何我写的 class 实现一些接口(如ApplicationContextAware)后并放入容器中, 就可以获取到一些对象(如applicationContext)? 1 2 3 1) 首先 AbstractApplicationContext#prepareBeanFactory 会添加一个ApplicationContextAwareProcessor 2) 这个 beanPostProcessor 负责在bean初始化之前注入context对象. 3) 这个 beanPostProcessor 的执行时机是在 doCreateBean 中的 postProcessBeforeInitialization()
为何我写的 class 实现 ApplicationListener 后并放入容器中, 就能监听我想知道的事件? 1 2 3 4 1) 在 AbstractApplicationContext#registerListeners() 中扫描容器内所有相关实现类加入到事件监听者集合中 2) 然后在publishEvent时,遍历事件监听者集合调用bean的方法即可。观察者模式! 3) 另外也用了BeanPostProcessor去实现, 叫 ApplicationListenerDetector, 加入时机同1, 执行时机同1. 4) 至于为何使用2种机制, 应该是因为 registerListeners() 时, 扫描只是当前的, 后续可能容器内的 bean 还会增加(我也猜不到啥形式增加, 反正简单写个类肯定不会), 所以还是需要 ApplicationListenerDetector 在这个 Bean 初始化时加入到监听者中去.
为何Spring中遇到各种顺序问题, 只需要实现 Ordered 接口(或加上@Order注解)就能使其有序?
因为 Spring 预先在执行这些东西之前, 进行一个排序动作, 然后才遍历执行. 包括AOP, BeanFactoryPostProcessor, BeanPostProcessor .
1 2 1) 比如说 BeanPostProcesser, 容器扫描后, 会像对bean集合排序, 再遍历执行. 2) 详细过程见 PostProcessorRegistrationDelegate#sortPostProcessors()
Spring是如何解决循环依赖的(指用字段注入而非构造方法)? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 ) 首先, 假定有两个单例 bean A 和 B, A 持有 B, B 持有A, 构成循环2 ) 此时程序调用getBean获取A,则在 doCreateBean 中 创建后将 bean 缓存到 singletonFactories 中3 ) 然后设置属性B, 解析属性, 需要获取B对象4 ) 获取B, 则执行doCreateBean 后执行解析属性, 需要获取 A对象 (又一次)5 ) 获取A, 进入 doGetBean 中的 getSingleton, 此时判断 singletonFactories 中有A, 则可以直接取出A6 ) 获得A后, 即可完成B的属性赋值, 然后会完成B的创建.7 ) B创建完后, A就能获得B, 则A也完成了属性赋值, 最后完成创建A.8 ) 到此, 返回即可.> 总结: 首次获取A, 创建A对象后缓存一个存储A对象的 ObjectFactory 实例, 再解析属性时触发 getBean(B), 同理也会做缓存, 然后也解析属性, 触发getBean(A), 第二次获取A, 进入另一个逻辑, 返回 ObjectFactory 实例中存储的对象A, 即可完成getBean(A), 然后完成getBean(B), 再完成外层的getBean(A). TIPS: 步骤4 中, 会先判断 earlySingletonObjects, 不存在才判断 singletonFactories, 而从 singletonFactories 中取得对象后, 则会将其从 singletonFactories 移除并加入 earlySingletonObjects 这是因为 singletonFactories 缓存的 FactoryBean, 若反复调用 getObject(), 则每次获取都会调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference 方法, 而此方法会执行 SmartInstantiationAwareBeanPostProcessor 的 getEarlyBeanReference(), 这会导致 BeanPostProcessor 重复执行, 显然是不行的.
Spring可以用注解替换XML配置文件了, 是如何实现的呢(常用注解的实现原理)? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1) 首先是指定包名或指定类名 如指定包名则 scan 时会执行, 如指定类名则在构造方法初始化 reader 时执行 2) 无论哪种, 最终都会走一段代码 AnnotationConfigUtils#registerAnnotationConfigProcessors() 3) 这段代码会添加一些 BeanFactoryPostProcessor 如 ConfigurationClassPostProcessor 负责解析 @Configuration/@Import/@Bean 等注解 然后由 ConfigurationClassBeanDefinitionReader 负责将信息转换成BeanDefinition再注册到容器。 如 AutowiredAnnotationBeanPostProcessor 负责解析 @Autowired/@Value 注解 如 CommonAnnotationBeanPostProcessor 负责解析 @Resource 注解 解析放在 postProcessProperties() 方法中, 先扫描bean的字段和方法, 然后一一调用方法和为字段注入值 4) 之后, 他会将扫描的类放到 beanDefinitions 中(或指定的类注册进去) 5) BeanFactory加载完毕后, 回到AbstractApplicationContext的refresh逻辑 如会执行 postProcessBeanFactory(), 调用前面加入的ConfigurationClassPostProcessor 然后会添加更多的类到容器中. 注意事项: @Configuration 和 @Component的区别? 观察发现,即使使用@Component 其下带 @Bean 的方法依然可以注入到容器中。所以似乎两者没有区别? 仔细查看源码和资料后,发现 postProcessBeanFactory() 方法在 processConfigBeanDefinitions() 后还会调用 enhanceConfigurationClasses() 而在这个方法中, 对前面解析了class 是 CONFIGURATION_CLASS_FULL (即代表@Configuration)的类 会生成一个 cglib 的代理, 这样获取@Bean注解的方法的bean时,不会每次调用方法new 一个, 而是有缓存.
总结: 就是利用 BeanFactoryPostProcessor 可获取 BeanDefinitionRegistry 对象, 然后扫描容器内带有注解的 bean, 解析这些注解得到一些 BeanDefinition, 再通过获得的 BeanDefinitionRegistry对象注册到 BeanFactory 中.
Spring AOP是如何实现的(指@Aspect)? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1) 使用 @EnableAspectJAutoProxy 2) @EnableAspectJAutoProxy 中使用了 @Import(AspectJAutoProxyRegistrar.class) 3) ConfigurationClassPostProcessor 会解析@Import, 进入 registerBeanDefinitions() 中 4) registerBeanDefinitions() 中添加了 AnnotationAwareAspectJAutoProxyCreator 到容器中 5) AnnotationAwareAspectJAutoProxyCreator 本质上时一个 BeanPostProcessor 6) 因此在 createBean 时, 会被自动调用. 其中 postProcessAfterInitialization() 负责创建代理对象 7) 而 getAdvicesAndAdvisorsForBean() 则负责查找对应的增强. 然后会调用子类的findCandidateAdvisors 8) 如 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() 负责注解编写增强@Before/@After等 9) 简单说下逻辑, 就是查找容器所有类, 判断这个类有没有 @Aspect 注解, 然后先找出所有Pointcut 再遍历所有方法, 找出方法上带有@Before等注解且有关联的Pointcut的方法, 然后使用这个方法和关联的Pointcut 来new 一个Advisor, 加入到Advisor集合中, 遍历结束后返回即可. 10) 查找到所有的增强后, 再比较Pointcut表达式是否匹配当前的bean, 如可以则加入. 11) 根据找到的Advisor集合, 创建一个带配置(advisor集合等)的代理对象, 代理对象执行方法前 12) 会先根据配置中的advisor集合生成一个执行链, 然后在拦截代理方法处调用. 执行链会负责执行通知. 13) 不同的通知由不同的适配器执行.
总结就是通过 @EnableAspectJAutoProxy 的@Import, 使得程序最终会执行 AnnotationAwareAspectJAutoProxyCreator 的 postProcessAfterInitialization(对象初始化后调用) 方法, 这个方法在 BeanFactory创建完对象后触发, 此时便可通过 CGlib 等动态代理技术为 创建的 bean 对象创建一个代理对象, 然后这个代理对象会根据 Pointcut 找到关联的 Advisor, 并在合适的时机执行对应的 Advisor, 如 @Before产生的Advisor 会在执行了 bean 对象的指定方法(看Pointcut配置)后执行.
Spring 事务是如何实现的(指@Transaction)? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 0) 事务是由AOP实现的, 所以需要找到对应的Pointcut 和 Advisor 1) 打开了 @EnableTransactionManagement 注解 2) 然后@Import 了 TransactionManagementConfigurationSelector 3) 之后导入了 ProxyTransactionManagementConfiguration 到容器中 4) ProxyTransactionManagementConfiguration 带有 @Configuration 5) @Bean 注入了一个通用的Advisor: BeanFactoryTransactionAttributeSourceAdvisor 6) 这个Advisor的 Pointcut 是由 TransactionAttributeSourcePointcut 实现的 实现逻辑是 TransactionAttributeSourcePointcut 的 matches() 这个方法调用了 getTransactionAttributeSource() 获取 AnnotationTransactionAttributeSource 然后通过 getTransactionAttribute() 调用了 findTransactionAttribute() 最终使用SpringTransactionAnnotationParser 类判断方法是否有@Transactional注解 并解析注解信息然后返回. 另外这个方法还可以获取@Transactional注解的信息, 而这里只用于判断是否需要拦截这个方法. 7) TransactionInterceptor 是一个Advisor 也可以通过AnnotationTransactionAttributeSource获取@Transactional注解上的信息 然后在invoke中, 拦截方法, 打开事务, 在执行完方法后, 提交事务, 报错时回滚事务 这个 Advisor 不同于传统的前置/后置, 而是更具体的 MethodInterceptor(动态代理直接相关).
总结: 就是基于AOP实现的, 只需找到对应的 Pointcut 和 Advisor 即可. Pointcut 就是根据 @Transaction 注解判断方法是否需要代理, 这个很简单; 比较有意思的是 Advisor 不是我们写AOP那种 @Before,@Around之类的, 而是更接近动态代理原始的语法的 MethodInterceptor 即 TransactionInterceptor.
BeanFactoryPostProcessor 相关类分析 BeanFactoryPostProcessor 生效原理
生效原理就是, ApplicationContext 的 refresh 方法中会扫描出容器中实现了 BeanFactoryPostProcessor 接口的 bean, 将其排序后执行相应的接口, 这样我们写的类实现的相应的接口的方法就被执行了.
1 2 3 常用的 BeanFactoryPostProcessor 这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan 等基础注解. 是注解开发的基石, 更是 Spring Boot 的基石.
BeanPostProcessor 相关类分析 BeanPostProcessor 生效原理
在 refresh() 中会扫描容器中所有 实现了 BeanPostProcessor 接口的类, 添加到 BeanFactory 的 beanPostProcessors 字段中(是个List[CopyOnWriteArrayList自定义版, 自定义加入了清空缓存的逻辑]), 然后在 BeanFactory 创建对象时 createBean() 在适当的时机调用对应的方法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 有哪几种 BeanPostProcessor (默认的+扩展) 1.InstantiationAwareBeanPostProcessor postProcessAfterInstantiation: 对象实例化后调用 postProcessBeforeInstantiation: 对象实例化前调用 postProcessProperties: 设置属性值前 postProcessPropertyValues: 设置属性值前, 若上个方法不处理(返回null)才会触发 2.SmartInstantiationAwareBeanPostProcessor predictBeanType: 获取一个 bean 的 class 类型前调用 getEarlyBeanReference: 获取一个二级缓存对象(singletonFactories的getObject)时调用 determineCandidateConstructors: 决定一个 bean 实例化的构造参数是什么时调用 3.DestructionAwareBeanPostProcessor postProcessBeforeDestruction: 对象销毁前调用 requiresDestruction: 判断这个类针对某个 bean 是否执行 postProcessBeforeDestruction() 4.MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition: 在创建对象前调用, 可对 BeanDefinition 做修改 resetBeanDefinition: 在重置 BeanDefinition 时调用, 用于清空 PostProcessor 对应的缓存 5.BeanPostProcessor(基础) postProcessBeforeInitialization: 创建对象后(也设置好了字段), 在调用 init 之前调用 postProcessAfterInitialization: 在创建对象时, 调用了 init 之后调用 总结: 0.对 BeanDefinition 做干预 1.对象实例化过程中(对class/构造参数进行干预) 2.对象实例化前后 3.对象设置属性前, 对属性做干预 4.对象初始化(init)前后 5.对象销毁前
调用时机 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁
1 2 3 4 5 6 7 1.AsyncAnnotationBeanPostProcessor: 用于在将 @Async 相应的 Advisor 加入到对象的代理中 2.ScheduledAnnotationBeanPostProcessor: 用于处理 @Scheduled 注解, 将 bean 生产代理类 3.AnnotationAwareAspectJAutoProxyCreator: AOP 实现核心类 4.AutowiredAnnotationBeanPostProcessor: 用于处理 @Autowired 注解 5.ApplicationListenerDetector: 用于处理实现 ApplicationListener 接口的 bean 对象, 将其添加到事件广播器的监听者集合中. ...