首页 > 其他分享 >seata数据源代理

seata数据源代理

时间:2023-03-03 10:35:18浏览次数:31  
标签:origin return seata 数据源 Object 代理 bean proxy DataSource

seata数据源代理流程

1-SeataDataSourceAutoConfiguration

创建SeataAutoDataSourceProxyCreator对象,默认seata模式为AT

2-SeataAutoDataSourceProxyCreator

  • 设置advisor用于来接实现DataSource接口的实现类
    public SeataAutoDataSourceProxyCreator(boolean useJdkProxy, String[] excludes, String dataSourceProxyMode) {
          setProxyTargetClass(!useJdkProxy);
          this.excludes = new HashSet<>(Arrays.asList(excludes));
          // AT
          this.dataSourceProxyMode = dataSourceProxyMode;
          this.advisors = buildAdvisors(dataSourceProxyMode);
      }
    
      private Object[] buildAdvisors(String dataSourceProxyMode) {
          Advice advice = new SeataAutoDataSourceProxyAdvice(dataSourceProxyMode);
          return new Object[]{new DefaultIntroductionAdvisor(advice)};
      }
    
  • 重写wrapIfNecessary,设置数据源代理
    @Override
      protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
          // we only care DataSource bean
          if (!(bean instanceof DataSource)) {
              return bean;
          }
    
          // when this bean is just a simple DataSource, not SeataDataSourceProxy
          LOGGER.error("bean={}", bean.getClass().getSimpleName());
          if (!(bean instanceof SeataDataSourceProxy)) {
              Object enhancer = super.wrapIfNecessary(bean, beanName, cacheKey);
              // this mean this bean is either excluded by user or had been proxy before
              if (bean == enhancer) {
                  return bean;
              }
              // else, build proxy,  put <origin, proxy> to holder and return enhancer
              DataSource origin = (DataSource) bean;
              SeataDataSourceProxy proxy = buildProxy(origin, dataSourceProxyMode);
              DataSourceProxyHolder.put(origin, proxy);
              LOGGER.error("bean2origin={}, proxy={}, proxy.targetDataSource={}", origin.getClass().getSimpleName(), proxy.getClass().getSimpleName(), proxy.getTargetDataSource());
              return enhancer;
          }
    
          /*
           * things get dangerous when you try to register SeataDataSourceProxy bean by yourself!
           * if you insist on doing so, you must make sure your method return type is DataSource,
           * because this processor will never return any subclass of SeataDataSourceProxy
           */
          LOGGER.warn("Manually register SeataDataSourceProxy(or its subclass) bean is discouraged! bean name: {}", beanName);
          SeataDataSourceProxy proxy = (SeataDataSourceProxy) bean;
          DataSource origin = proxy.getTargetDataSource();
          LOGGER.error("TargetDataSource={}", origin.getClass().getSimpleName());
          Object originEnhancer = super.wrapIfNecessary(origin, beanName, cacheKey);
          // this mean origin is either excluded by user or had been proxy before
          if (origin == originEnhancer) {
              return origin;
          }
          // else, put <origin, proxy> to holder and return originEnhancer
          DataSourceProxyHolder.put(origin, proxy);
          return originEnhancer;
      }
    

3-SeataAutoDataSourceProxyAdvice

所有实现DataSource接口的实现类都会再次被拦截,调用invoke方法

@Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // check whether current context is expected
        if (!inExpectedContext()) {
            return invocation.proceed();
        }

        Method method = invocation.getMethod();
        String name = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();

        Method declared;
        try {
            declared = DataSource.class.getDeclaredMethod(name, parameterTypes);
        } catch (NoSuchMethodException e) {
            // mean this method is not declared by DataSource
            return invocation.proceed();
        }

        // switch invoke instance to its proxy
        DataSource origin = (DataSource) invocation.getThis();
        SeataDataSourceProxy proxy = DataSourceProxyHolder.get(origin);
        Object[] args = invocation.getArguments();
        LOGGER.error("执行类={},执行方法={},方法参数={}", proxy.getClass().getSimpleName(), declared.getName(), args);
        return declared.invoke(proxy, args);
    }

标签:origin,return,seata,数据源,Object,代理,bean,proxy,DataSource
From: https://www.cnblogs.com/demon001/p/17174672.html

相关文章

  • 10_Spring_CGLIB动态代理
     proxy动态代理面向接口1必须有接口和实现类 2增强接口中定义的方法3只能读取接口中方法的上注解cglib动态代理模式面向父类 packagecom.msb.testCglib;importo......
  • 10_Spring_CGLIB动态代理
     proxy动态代理面向接口1必须有接口和实现类 2增强接口中定义的方法3只能读取接口中方法的上注解cglib动态代理模式面向父类 packagecom.msb.testCglib;importo......
  • unixODBC 不使用GUI配置数据源
     {PurposeAlotofpeopleareusingunixODBCbutforanumberofreasonsarenotbuildingtheGUIconfigurationandtestingtools(ODBCConfigandDataManage......
  • 10_Spring_CGLIB动态代理
    ​ proxy动态代理面向接口1必须有接口和实现类 2增强接口中定义的方法3只能读取接口中方法的上注解cglib动态代理模式面向父类 packagecom.msb.testCglib......
  • 10_Spring_CGLIB动态代理
    ​ proxy动态代理面向接口1必须有接口和实现类 2增强接口中定义的方法3只能读取接口中方法的上注解cglib动态代理模式面向父类 packagecom.msb.testCglib......
  • python3和scrapy使用亿牛云隧道代理问题以及代码
    一、前言近期,我参与了一个需要爬取国家食品药品监督局数据的项目,但该网站存在IP屏蔽机制。因此,我需要在Scrapy框架中实现自动IP切换,才能完成任务。然而,尽管我使用了第三方......
  • HTTP代理如何爬取?保姆式教程(附测试视频)
    在网络爬虫的应用中,HTTP代理的使用是常见的技术手段之一。通过使用HTTP代理,爬虫可以模拟不同的访问来源,避免被目标网站识别出爬虫行为,从而提高爬虫的成功率和效率。那么,如何......
  • EBS 查找数据源(FORM篇)
    在OracleE-BusinessSuite环境下进行二次开发,要求技术顾问对EBS系统的结构和实现有一定的了解,同时熟悉系统的关键流程,进而掌握后台的表结构设计,查找数据源需要达到的两个......
  • 九、MybatisPlus的多数据源
    场景适用于多种场景:纯粹多库、读写分离、一主多从、混合模式等目前我们就来模拟一个纯粹多库的一个场景,其他场景类似场景说明:我们创建两个库,分别为:mybatis_plus(以前......
  • nginx反向代理搭建web网站问题
    搭建过程中遇到的问题记录:1、ubuntu更改端口号sudovi/etc/apache2/ports.conf修改监听端口以及主机端口为8080NameVirtualHost*:8080Listen8080sudovi/etc/......