java 如何使Spring lib项目根据用户依赖关系动态启用类

zf9nrax1  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(83)

我想用一个例子来说明我的真实的问题,
这是一个分布式锁的小项目,其目的是通过属性文件配置分布式锁,使用时不需要考虑其实现。
您可以像这样配置分布式锁属性文件

dlock:
  list: # this is a Map List
    - namespace: redis-dlock-1
      type: redis
      config: # the config includes specific impl properties, here is redisson
        ...
    - namespace: db-dlock-1
      type: database
      config: # here is database config
        ...
    - namespace: zk-dlock-1
      type: zookeeper
      config: # here is curator config
        ...
    ...

在项目中使用分布式锁时,您只需导入依赖项,创建配置文件,并在项目中使用Annotation或API,如下所示

// this is a user method
@DistributedLock(namespace="redis-dlock-1", tryWait=3000, fair=false)
public void invoke(Object[] params) {
  ......
}

public void invoke(Object[] params) {
  DLock lock = DLockSupport.getDLock(/* namespace = */ "db-dlock-1", /* fair = */false);
  ......
  if (lock.tryLock(3000)) {
    ...... // do bussiness
    lock.unlock(); 
  }
  ......
}

它很容易制作和使用,但正如我提到的,分布式锁有3个impl:database, zookeeper, redis,为了避免用户主动选择其impl,它们位于同一个项目com.example.dlock:distributed-lock

distributed-lock
     |
    impl
       |
      redis
      zookeeper
      database

但是我发现一个问题,即使我的项目几乎只使用redis impl,导入分布式锁也会导致导入数据库和zookeeper依赖,这是我不想看到的
换句话说,我想让库的impl只有在它的基本依赖已经被用户项目导入时才有效。也就是说,如果只有redison(redis),那么zookeeper和数据库是无效的,如果有redison(redis)和数据库,那么使用zookeeper是无效的,如果env有所有的impl依赖,那么你可以使用任何分布式锁的impl
我的配置设计是这样的:

@Configuration
@Import(RedisDLockConfiguration.class, 
        ZookeeperDLockConfiguration.class, 
        DatabaseDLockConfiguration.class)
public class DLockAutoConfiguration { }

@ConditionalOnClass({RedisTemplate.class, RedissonClient.class})
@EnableConfigurationProperties(RedisDLockProperties.class)
public class RedisDLockConfiguration {
    ......
}

@ConditionalOnClass({Zookeeper.class, CuratorFramework.class})
@EnableConfigurationProperties(ZookeeperDLockProperties.class) 
public class ZookeeperDLockConfiguration {
    ......
}

@ConditionalOnClass({JdbcTemplate.class, Connection.class})
@EnableConfigurationProperties(DatabaseDLockProperties.class)
public class DatabaseDLockConfiguration {
    ......
}

因此,在我的赋值中,如果用户classpath包含RedisTemplate.class,RedissonClient.class,则将启用redis-dlock,与数据库和zookeeper相同,instead if user lack some class, and it should be ignored and ok, but actually i got missing class error
我的真实的问题就像这个例子一样,我继承了一个旧的spring-cloud lib系统,并命令升级到2021.0.X,系统源代码在一个普通模块中包含一个ZuulFilter,所以我将其替换为springcloud-gateway的GlobalFilter,我以为它会在gateway导入的环境中启用,而在普通env中禁用,但我错了,它导入了很多gateway的类和bean,这太重了,无法接受
有没有办法实现目标?

o7jaxewo

o7jaxewo1#

distributed-lock的每个实现移动到一个单独的Maven模块中,这样应用程序就可以只在它们真正想要使用的模块上声明依赖项。在应用程序中,避免显式导入distributed-lock的3个实现的配置类:可以使用@ComponentScan@Autoconfiguration

相关问题