gpt4 book ai didi

java - spring中条件注解的排序评估

转载 作者:行者123 更新时间:2023-12-02 12:55:04 25 4
gpt4 key购买 nike

我有三个类,所有这些类都需要根据 @ConditionalOnExpression 注释启用/禁用。所有这些都位于单独的 .java 文件中。

例如:

@ConditionalOnExpression("#T(com.xxx.xxx.xxx.xxx.CxProperties).isAEnabled()}")
Class A{
}


@ConditionalOnExpression("#T(com.xxx.xxx.xxx.xxx.CxProperties).isBEnabled()}")
Class B{
}


@ConditionalOnExpression("#T(com.xxx.xxx.xxx.xxx.CxProperties).isCEnabled()}")
Class C{
}

现在我在另一个类中有一个 init 函数,它首先执行,并且我将启用/禁用值设置为类 CxProperties。注意:假设所有 setter 都是静态的

class setvalues{

public void init(){
/*Read config values from a file*/
CxProperties.setAEnabled(true/false);
CxProperties.setBEnabled(true/false);
CxProperties.setCEnabled(true/false);
}
}

现在,当根本未设置启用/禁用时,这些条件的评估发生在程序开始时(甚至在执行 init 之前)。

在 spring 中是否有任何可能的方法来命令对这些条件进行评估,例如在执行的某个点后评估此条件?

非常感谢任何指点。

最佳答案

我建议您不要为此使用 @ConditionalOnExpression 注释。

考虑使用@PreAuthorize。是的,它来自 spring-security。

这样,您可以保护每个服务在未启用的情况下不被使用,并动态切换其启用/禁用状态:

@SpringBootApplication
public class So44462763Application {

public static void main(String[] args) {
SpringApplication.run(So44462763Application.class, args);
}

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // <-- this is required for PreAuthorize annotation to work
public static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}

interface CxProperties {
boolean isServiceAEnabled();
boolean isServiceBEnabled();
boolean isServiceCEnabled();

boolean enableService(String service);
boolean disableService(String service);
}

@Component("cx")
public static class CxPropertiesImpl implements CxProperties {
private static final ConcurrentHashMap<String, Boolean> services = new ConcurrentHashMap<>(); //could be database/redis/property file/etc

@PostConstruct
private void init() {
//services.put("serviceA", true); //initial population from property file/network resource/whatever
}

public boolean isServiceAEnabled() {
return services.getOrDefault("serviceA", false);
}

public boolean isServiceBEnabled() {
return services.getOrDefault("serviceB", false);
}

public boolean isServiceCEnabled() {
return services.getOrDefault("serviceC", false);
}
//just a sample how you can dynamically control availability for each service
@Override
public boolean enableService(String service) {
services.put(service, true);
return services.getOrDefault(service, false);
}

@Override
public boolean disableService(String service) {
services.put(service, false);
return services.getOrDefault(service, false);
}
}

interface BusinessService {
String doSomething();
}

@Service("serviceA")
@PreAuthorize("@cx.serviceAEnabled")
public static class ServiceA implements BusinessService {

@Override
public String doSomething() {
return this.getClass().getSimpleName() + " doing some work";
}
}

@Service("serviceB")
@PreAuthorize("@cx.serviceBEnabled")
public static class ServiceB implements BusinessService {

@Override
public String doSomething() {
return this.getClass().getSimpleName() + " doing some work";
}
}

@Service("serviceC")
@PreAuthorize("@cx.serviceCEnabled")
public static class ServiceC implements BusinessService {

@Override
public String doSomething() {
return this.getClass().getSimpleName() + " doing some work";
}
}

@RestController
@RequestMapping("/api/work")
public static class WorkApi {
private static final Logger log = LoggerFactory.getLogger(WorkApi.class);

private final List<BusinessService> businessServices;

@Autowired
public WorkApi(final List<BusinessService> businessServices) {
this.businessServices = businessServices;
}

@GetMapping
public String doWork() {
final StringJoiner joiner = new StringJoiner(",");
for (BusinessService service : businessServices) {
try {
joiner.add(service.doSomething());
} catch (AccessDeniedException e) {
log.warn("Service {} is disabled.", service);
}
}
return joiner.toString();
}
}

@RestController
@RequestMapping("/api/control")
public static class ControlApi {

private final CxProperties cxProperties;

@Autowired
public ControlApi(final CxProperties cxProperties) {
this.cxProperties = cxProperties;
}

@PostMapping("{service}/enable")
public boolean enable(@PathVariable("service") String serviceName) {
return cxProperties.enableService(serviceName);
}

@PostMapping("{service}/disable")
public boolean disable(@PathVariable("service") String serviceName) {
return cxProperties.disableService(serviceName);
}
}
}

这是一个示例用法:

$ curl -u user:123 -XGET 'localhost:8080/api/work'
$ curl -u user:123 -XPOST 'localhost:8080/api/control/serviceC/enable'
true%
$ curl -u user:123 -XGET 'localhost:8080/api/work'
ServiceC doing some work%
$ curl -u user:123 -XPOST 'localhost:8080/api/control/serviceA/enable'
true%
$ curl -u user:123 -XGET 'localhost:8080/api/work'
ServiceA doing some work,ServiceC doing some work%

使用这种方法,即使不重新启动,您也可以控制服务的可访问性。

所有这些都可以在没有 spring-security 的情况下完成,但需要更多的手动工作,并且可能会稍微降低代码的整体可读性。

关于java - spring中条件注解的排序评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44462763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com