个人随笔
目录
一个简单的例子来探寻Spring事务Trasanction执行源码的主脉络(一):创建事务代理对象
2021-08-13 21:51:56

我们主要是从配置类入手.

  1. @Configuration
  2. @ComponentScan(basePackages="suibibk")
  3. @EnableTransactionManagement
  4. public class MyConfiguration {
  5. private String dbUrl = PropertiesUtil.get("dataSource.url");
  6. private String username =PropertiesUtil.get("dataSource.username");
  7. private String password =PropertiesUtil.get("dataSource.password");
  8. private String driverClassName =PropertiesUtil.get("dataSource.driver");
  9. private int initialSize=Integer.parseInt(PropertiesUtil.get("dataSource.initialSize","5"));
  10. private int minIdle= Integer.parseInt(PropertiesUtil.get("dataSource.minIdle","5"));
  11. private int maxActive= Integer.parseInt(PropertiesUtil.get("dataSource.maxActive","20"));
  12. private int maxWait= Integer.parseInt(PropertiesUtil.get("dataSource.maxWait","60000"));
  13. private int timeBetweenEvictionRunsMillis= Integer.parseInt(PropertiesUtil.get("dataSource.timeBetweenEvictionRunsMillis","60000"));
  14. private int minEvictableIdleTimeMillis= Integer.parseInt(PropertiesUtil.get("dataSource.minEvictableIdleTimeMillis","300000"));
  15. private String validationQuery= PropertiesUtil.get("dataSource.validationQuery","SELECT 1 FROM DUAL");
  16. private boolean testWhileIdle= Boolean.parseBoolean(PropertiesUtil.get("dataSource.testWhileIdle","true"));
  17. private boolean testOnBorrow= Boolean.parseBoolean(PropertiesUtil.get("dataSource.testOnBorrow","false"));
  18. private boolean testOnReturn= Boolean.parseBoolean(PropertiesUtil.get("dataSource.testOnReturn","false"));
  19. private boolean poolPreparedStatements=Boolean.parseBoolean(PropertiesUtil.get("dataSource.poolPreparedStatements","true"));
  20. private int maxPoolPreparedStatementPerConnectionSize= Integer.parseInt(PropertiesUtil.get("dataSource.maxPoolPreparedStatementPerConnectionSize","20"));
  21. //wall, 去掉这个,不然会报sql injection violation
  22. private String filters= PropertiesUtil.get("dataSource.filters","stat,log4j");
  23. private String connectionProperties= PropertiesUtil.get("dataSource.connectionProperties","druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");
  24. @Bean //声明其为Bean实例
  25. @Primary //在同样的DataSource中,首先使用被标注的DataSource
  26. public DataSource dataSource() {
  27. DruidDataSource datasource = new DruidDataSource();
  28. datasource.setUrl(this.dbUrl);
  29. datasource.setUsername(username);
  30. datasource.setPassword(password);
  31. datasource.setDriverClassName(driverClassName);
  32. //configuration
  33. datasource.setInitialSize(initialSize);
  34. datasource.setMinIdle(minIdle);
  35. datasource.setMaxActive(maxActive);
  36. datasource.setMaxWait(maxWait);
  37. datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
  38. datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
  39. datasource.setValidationQuery(validationQuery);
  40. datasource.setTestWhileIdle(testWhileIdle);
  41. datasource.setTestOnBorrow(testOnBorrow);
  42. datasource.setTestOnReturn(testOnReturn);
  43. datasource.setPoolPreparedStatements(poolPreparedStatements);
  44. datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
  45. try {
  46. datasource.setFilters(filters);
  47. } catch (SQLException e) {
  48. e.printStackTrace();
  49. }
  50. datasource.setConnectionProperties(connectionProperties);
  51. return datasource;
  52. }
  53. @Bean
  54. public JdbcTemplate jdbcTemplate(DataSource datasource) {
  55. return new JdbcTemplate(datasource);
  56. }
  57. @Bean
  58. public PlatformTransactionManager transactionManager(DataSource dataSource) {
  59. return new DataSourceTransactionManager(dataSource);
  60. }
  61. }

其实看过AOP源码的都知道,事务远比AOP简单的多,我们首先找到开启事务的关键注解

  1. @EnableTransactionManagement

点进去发现

  1. @Import(TransactionManagementConfigurationSelector.class)

而我们知道TransactionManagementConfigurationSelector实现了ImportSelector接口,所以会制动调用它的selectImports方法,返回对象

  1. @Override
  2. protected String[] selectImports(AdviceMode adviceMode) {
  3. switch (adviceMode) {
  4. case PROXY:
  5. return new String[] {AutoProxyRegistrar.class.getName(),
  6. ProxyTransactionManagementConfiguration.class.getName()};
  7. case ASPECTJ:
  8. return new String[] {determineTransactionAspectClass()};
  9. default:
  10. return null;
  11. }
  12. }

也就是会生成如下连个对象

  1. AutoProxyRegistrar
  2. ProxyTransactionManagementConfiguration

我们一个个来分析

一、AutoProxyRegistrar

  1. public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar

我们很熟悉,之前AOP也是跟这个一样的,再解析完配置类后会调用这个对象的registerBeanDefinitions方法,然后注入一个类

  1. @Override
  2. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  3. boolean candidateFound = false;
  4. Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
  5. for (String annType : annTypes) {
  6. AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
  7. if (candidate == null) {
  8. continue;
  9. }
  10. Object mode = candidate.get("mode");
  11. Object proxyTargetClass = candidate.get("proxyTargetClass");
  12. if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
  13. Boolean.class == proxyTargetClass.getClass()) {
  14. candidateFound = true;
  15. if (mode == AdviceMode.PROXY) {
  16. AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
  17. if ((Boolean) proxyTargetClass) {
  18. AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
  19. return;
  20. }
  21. }
  22. }
  23. }
  24. if (!candidateFound && logger.isInfoEnabled()) {
  25. String name = getClass().getSimpleName();
  26. logger.info(String.format("%s was imported but no annotations were found " +
  27. "having both 'mode' and 'proxyTargetClass' attributes of type " +
  28. "AdviceMode and boolean respectively. This means that auto proxy " +
  29. "creator registration and configuration may not have occurred as " +
  30. "intended, and components may not be proxied as expected. Check to " +
  31. "ensure that %s has been @Import'ed on the same class where these " +
  32. "annotations are declared; otherwise remove the import of %s " +
  33. "altogether.", name, name, name));
  34. }
  35. }

看这行代码

  1. AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

是不是很熟悉

  1. @Nullable
  2. public static BeanDefinition registerAutoProxyCreatorIfNecessary(
  3. BeanDefinitionRegistry registry, @Nullable Object source) {
  4. return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
  5. }

最终会加载InfrastructureAdvisorAutoProxyCreator对象,这个是跟AOP的AnnotationAwareAspectJAutoProxyCreator一个级别的,那后面代码的跟中也很明确了,当然是直接找

  1. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

  1. @Override
  2. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  3. if (bean != null) {
  4. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  5. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  6. return wrapIfNecessary(bean, beanName, cacheKey);
  7. }
  8. }
  9. return bean;
  10. }

好这里暂时不提,我们先看第二个类干了啥

二、ProxyTransactionManagementConfiguration

  1. @Configuration(proxyBeanMethods = false)
  2. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  3. public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
  4. @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
  5. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  6. public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
  7. TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
  8. BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
  9. advisor.setTransactionAttributeSource(transactionAttributeSource);
  10. advisor.setAdvice(transactionInterceptor);
  11. if (this.enableTx != null) {
  12. advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
  13. }
  14. return advisor;
  15. }
  16. @Bean
  17. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  18. public TransactionAttributeSource transactionAttributeSource() {
  19. return new AnnotationTransactionAttributeSource();
  20. }
  21. @Bean
  22. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  23. public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
  24. TransactionInterceptor interceptor = new TransactionInterceptor();
  25. interceptor.setTransactionAttributeSource(transactionAttributeSource);
  26. if (this.txManager != null) {
  27. interceptor.setTransactionManager(this.txManager);
  28. }
  29. return interceptor;
  30. }
  31. }

发现竟然是个配置类,也就是说会向容器中初始化三个bean

1、BeanFactoryTransactionAttributeSourceAdvisor

beanName=org.springframework.transaction.config.internalTransactionAdvisor
牛逼了,这里直接指定Advisor,完全不用跟AOP一样苦逼的扫描所有类,然后借助缓存,这个已经指定了,那么完全不用扫描对象了啊。

2、TransactionAttributeSource

这个暂时不知道用来干啥

3、TransactionInterceptor

事务拦截对象

  1. interceptor.setTransactionManager(this.txManager);

里面设置了我们的事务管理器,而我们的事务管理器是

  1. PlatformTransactionManager

这个接口里面定义了

  1. getTransaction(TransactionDefinition)
  2. commit(TransactionStatus)
  3. rollback(TransactionStatus)

这三个操作事务的方法。

我们在配置文件配置的是

  1. @Bean
  2. public PlatformTransactionManager transactionManager(DataSource dataSource) {
  3. return new DataSourceTransactionManager(dataSource);
  4. }

所以我猜想,我们后面的事务操作都会由DataSourceTransactionManager来完成

  1. dataSource : DataSource
  2. enforceReadOnly : boolean
  3. DataSourceTransactionManager()
  4. DataSourceTransactionManager(DataSource)
  5. setDataSource(DataSource)
  6. getDataSource()
  7. obtainDataSource()
  8. setEnforceReadOnly(boolean)
  9. isEnforceReadOnly()
  10. afterPropertiesSet()
  11. getResourceFactory()
  12. doGetTransaction()
  13. isExistingTransaction(Object)
  14. doBegin(Object, TransactionDefinition)
  15. doSuspend(Object)
  16. doResume(Object, Object)
  17. doCommit(DefaultTransactionStatus)
  18. doRollback(DefaultTransactionStatus)
  19. doSetRollbackOnly(DefaultTransactionStatus)
  20. doCleanupAfterCompletion(Object)
  21. prepareTransactionalConnection(Connection, TransactionDefinition)

好了,我们现在来看看什么时候会生成事务代理对象吧!

三、生成事务代理对象

前面我们说过最终会加载InfrastructureAdvisorAutoProxyCreator对象,这个是跟AOP的AnnotationAwareAspectJAutoProxyCreator一个级别的,因为并且因为ProxyTransactionManagementConfiguration加载bean的时候,直接指定了BeanFactoryTransactionAttributeSourceAdvisor,也就相当于没有必要进行全局扫描所有Object对象去找Advisor了,所以猜测不会在

  1. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

来做一些找到所有Advisor,然后放到缓存的行为

  1. @Override
  2. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
  3. Object cacheKey = getCacheKey(beanClass, beanName);
  4. if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
  5. if (this.advisedBeans.containsKey(cacheKey)) {
  6. return null;
  7. }
  8. if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return null;
  11. }
  12. }
  13. // Create proxy here if we have a custom TargetSource.
  14. // Suppresses unnecessary default instantiation of the target bean:
  15. // The TargetSource will handle target instances in a custom fashion.
  16. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  17. if (targetSource != null) {
  18. if (StringUtils.hasLength(beanName)) {
  19. this.targetSourcedBeans.add(beanName);
  20. }
  21. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  22. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  23. this.proxyTypes.put(cacheKey, proxy.getClass());
  24. return proxy;
  25. }
  26. return null;
  27. }

之前AOP是在

  1. shouldSkip(beanClass, beanName)

逻辑来处理的,现在我们的InfrastructureAdvisorAutoProxyCreator没有重写这个方法,所以不在这里操作,我们可以直接看

  1. @Override
  2. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  3. if (bean != null) {
  4. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  5. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  6. return wrapIfNecessary(bean, beanName, cacheKey);
  7. }
  8. }
  9. return bean;
  10. }

这里是跟AOP一样的,我们直接点进去

  1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  2. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  3. return bean;
  4. }
  5. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  6. return bean;
  7. }
  8. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return bean;
  11. }
  12. // Create proxy if we have advice.
  13. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  14. if (specificInterceptors != DO_NOT_PROXY) {
  15. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  16. Object proxy = createProxy(
  17. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  18. this.proxyTypes.put(cacheKey, proxy.getClass());
  19. return proxy;
  20. }
  21. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  22. return bean;
  23. }

找到关键代码

  1. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  1. @Override
  2. @Nullable
  3. protected Object[] getAdvicesAndAdvisorsForBean(
  4. Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  5. List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  6. if (advisors.isEmpty()) {
  7. return DO_NOT_PROXY;
  8. }
  9. return advisors.toArray();
  10. }
  1. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  2. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  3. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  4. extendAdvisors(eligibleAdvisors);
  5. if (!eligibleAdvisors.isEmpty()) {
  6. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  7. }
  8. return eligibleAdvisors;
  9. }
  1. protected List<Advisor> findCandidateAdvisors() {
  2. Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
  3. return this.advisorRetrievalHelper.findAdvisorBeans();
  4. }
  1. public List<Advisor> findAdvisorBeans() {
  2. // Determine list of advisor bean names, if not cached already.
  3. String[] advisorNames = this.cachedAdvisorBeanNames;
  4. if (advisorNames == null) {
  5. // Do not initialize FactoryBeans here: We need to leave all regular beans
  6. // uninitialized to let the auto-proxy creator apply to them!
  7. //1、这里会直接找到我们的bean:BeanFactoryTransactionAttributeSourceAdvisor
  8. advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  9. this.beanFactory, Advisor.class, true, false);
  10. this.cachedAdvisorBeanNames = advisorNames;
  11. }
  12. if (advisorNames.length == 0) {
  13. return new ArrayList<>();
  14. }
  15. List<Advisor> advisors = new ArrayList<>();
  16. for (String name : advisorNames) {
  17. if (isEligibleBean(name)) {
  18. if (this.beanFactory.isCurrentlyInCreation(name)) {
  19. if (logger.isTraceEnabled()) {
  20. logger.trace("Skipping currently created advisor '" + name + "'");
  21. }
  22. }
  23. else {
  24. try {
  25. advisors.add(this.beanFactory.getBean(name, Advisor.class));
  26. }
  27. catch (BeanCreationException ex) {
  28. Throwable rootCause = ex.getMostSpecificCause();
  29. if (rootCause instanceof BeanCurrentlyInCreationException) {
  30. BeanCreationException bce = (BeanCreationException) rootCause;
  31. String bceBeanName = bce.getBeanName();
  32. if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
  33. if (logger.isTraceEnabled()) {
  34. logger.trace("Skipping advisor '" + name +
  35. "' with dependency on currently created bean: " + ex.getMessage());
  36. }
  37. // Ignore: indicates a reference back to the bean we're trying to advise.
  38. // We want to find advisors other than the currently created bean itself.
  39. continue;
  40. }
  41. }
  42. throw ex;
  43. }
  44. }
  45. }
  46. }
  47. //这里就直接有内容返回了
  48. return advisors;
  49. }

后面就跟AOP一样生成代理对象了

  1. if (specificInterceptors != DO_NOT_PROXY) {
  2. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  3. Object proxy = createProxy(
  4. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  5. this.proxyTypes.put(cacheKey, proxy.getClass());
  6. return proxy;
  7. }

到这里大概脉络就完成了,接下来会写两篇文章分析下代理对象的执行逻辑,看看AOP是怎么执行的,事务又是怎么执行的。

参考:一个简单的例子来探寻SpringAOP执行源码的主脉络(一):创建代理对象

 222

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2