0

@ConditionalOnExpressionアノテーションに基づいて、すべて3つのクラスを有効/無効にする必要があります。これらはすべて独立した.javaファイルに入っています。春の条件付き注釈の順序評価

EX:

@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{ 
} 

今は最初に実行され、iはクラスCxPropertiesに有効/無効値を設定します異なるクラスの初期化目的球を持っています。 注:有効/無効が全く設定されていない場合、すべてのセッターを想定静的

class setvalues{ 

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

は今、これらの条件の評価は(さえINITの実行前)プログラムの先頭で起こっています。

実行時の特定のポイントの後にこれを評価するなど、これらの条件の評価を行うための春の方法はありますか?

いずれのポインタも高く評価されています。

+0

'@ ConditionalOnProperty'についてはどうですか? – fateddy

+0

私はアプリケーションを使用していません。https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html#boot-features-property-conditionsを参照してください。 ymlまたはプロパティファイル。私は、プロジェクト内で作られたカスタマイズされたファイルから設定データを読みました。したがって、クラスオブジェクトを評価する必要があります。しかし、とにかく、たとえ@ConditionalOnPropertyの場合でも、私たちはどのように評価を遅らせ/注文しますか? –

+0

私はそれが少なくともあなたが記述した方法では不可能だと信じています。しかし、それはいくつかの回避策かもしれません。より大きなスケールで達成しようとしていることを説明できますか? –

答えて

1

@ConditionalOnExpressionアノテーションを使用しないことをお勧めします。

代わりに@PreAuthorizeを使用することを検討してください。はい、それは春からのセキュリティです。

それが有効になっていて、動的にそれのために有効/無効状態を切り替えていない場合は、利用状況から各サービスを保護することができることをして

$ 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% 

@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); 
     } 
    } 
} 

そしてここでは、サンプルの使用でありますこの方法を使用すると、再起動しなくてもサービスのアクセシビリティを制御できます。

これはすべて、春のセキュリティなしでも実行できますが、少し手作業が必要となり、コード全体の可読性がわずかに低下する可能性があります。

+0

有効/無効設定は、ファイル(yamlまたはプロパティではない)から読み込まれ、プロセスの開始時に読み込まれます。そのデーモンは一度起動すると、ファイルから値を読み込み、クラスを有効/無効にする必要があります。それ以降、他の入力はどの形式でも受け付けません。 –

+0

動的にサービスを切り替えることは知っておくと良いことでした –

+0

それ以外の方法はありますか?(条件ファイルを読み込む)initメソッドを呼び出すようなものです。 –