Maison  >  Article  >  Java  >  Introduction au jugement conditionnel dans Spring Boot (avec code)

Introduction au jugement conditionnel dans Spring Boot (avec code)

不言
不言avant
2019-04-11 13:14:083588parcourir

Le contenu de cet article est une introduction au jugement conditionnel dans Spring Boot (avec code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Ces conditions dans Spring Boot

Spring Boot nous offre une multitude de conditions qui nous permettent d'ajouter des beans au conteneur dans le projet de manière très pratique. Cet article explique principalement chaque annotation et illustre son utilisation avec du code.

Toutes les annotations ConditionalOnXXX peuvent être placées sur une classe ou une méthode. Si la méthode est sur une classe, elle déterminera si toutes les méthodes annotées @Bean de la classe sont exécutées.

@Conditional

Les autres annotations conditionnelles ci-dessous sont du sucre syntaxique. Vous pouvez personnaliser ConditionalOnXXX via la méthode suivante.
L'annotation conditionnelle est définie comme suit, recevant le tableau de classe qui implémente le. Interface de conditions.

public @interface Conditional {
    Class extends Condition>[] value();
}

L'interface Condition n'a qu'une seule méthode matches, qui renvoie le résultat de la correspondance.

public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

Configurez les conditions via le système d'exploitation pour configurer Bean. Lorsque Window est utilisé, l'objet Person de Bill est instancié, et lorsque Linux est utilisé, l'objet Person de Linus est instancié.

//LinuxCondition,为方便起见,去掉判断代码,直接返回true了
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        return true;
    }
}
//WindowsCondition,为方便起见,去掉判断代码,直接返回false了
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
        return false;
    }
}
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
//配置类
@Configuration
public class BeanConfig {

    @Bean(name = "bill")
    @Conditional({WindowsCondition.class})
    public Person person1(){
        return new Person("Bill Gates",62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person2(){
        return new Person("Linus",48);
    }
}
public class AppTest {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);

    @Test
    public void test(){
        String osName = applicationContext.getEnvironment().getProperty("os.name");
        System.out.println("当前系统为:" + osName);
        Map<string> map = applicationContext.getBeansOfType(Person.class);
        System.out.println(map);
    }
}</string>

Résultat de sortie :

Le système actuel est : Mac OS X
{linus=Person(name=Linus, age=48)}

@ConditionalOnBean & @ConditionalOnMissingBean

Ces deux annotations jugeront l'objet Bean dans le conteneur Bean. L'exemple utilisé est lors de la configuration s'il s'avère qu'il n'y en a pas. Instance d'ordinateur, instanciez un ordinateur de sauvegarde.

@Data
@AllArgsConstructor
@ToString
public class Computer {
    private String name;
}
@Configuration
public class BeanConfig {
    @Bean(name = "notebookPC")
    public Computer computer1(){
        return new Computer("笔记本电脑");
    }

    @ConditionalOnMissingBean(Computer.class)
    @Bean("reservePC")
    public Computer computer2(){
        return new Computer("备用电脑");
    }
}
public class TestApp {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
    @Test
    public void test1(){
        Map<string> map = applicationContext.getBeansOfType(Computer.class);
        System.out.println(map);
    }
}</string>

Modifiez BeanConfig, si vous commentez le premier @Bean, l'ordinateur de sauvegarde sera instancié, sinon l'ordinateur de sauvegarde ne sera pas instancié

@ConditionalOnClass & @ConditionalOnMissingClass

Cette annotation déterminera s'il y a une classe spécifiée sur le chemin de classe. J'étais confus lorsque je l'ai vue pour la première fois. S'il n'y a pas de classe spécifiée sur le chemin de classe, la compilation ne réussira pas. .. Ceci est principalement utilisé lors de l'intégration de composants tiers avec la même fonction. Tant qu'il y a une classe du composant sur le chemin de classe, elle sera automatiquement configurée. Par exemple, lorsque Spring Boot Web configure automatiquement le. composant view, qu'il utilise Velocity, Thymeleaf ou freemaker, c'est la méthode utilisée.
L'exemple est deux ensembles d'armures A (combinaison légère) et B (combinaison sombre). Si A n'est pas présent, configurez B.

public interface Fighter {
    void fight();
}
public class FighterA implements Fighter {
    @Override
    public void fight() {
        System.out.println("使用光明套装");
    }
}
public class FighterB implements Fighter {
    @Override
    public void fight() {
        System.out.println("使用暗黑套装");
    }
}

Van est un samouraï et utilise la combinaison pour combattre

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Van {
    private Fighter fighter;
    public void fight(){
        fighter.fight();
    }
}

VanConfigA/B instancie le samouraï

@Configuration
@ConditionalOnClass({FighterA.class})
public class VanConfigA {
    @Primary
    @Bean
    public Van vanA(){
        return new Van(new FighterA());
    }
}
@Configuration
@ConditionalOnClass({FighterB.class})
public class VanConfigB {
    @Bean
    public Van vanB(){
        return new Van(new FighterB());
    }
}

Classe de test, par défaut, si suit AB Les deux sont sur le chemin de classe, les deux ensembles seront chargés et A sera défini sur PRIMARY. Si FightA.class est supprimé dans la classe cible, seul l'ensemble B sera chargé.

@SpringBootApplication
public class TestApp implements CommandLineRunner {
    @Autowired
    private Van van;
    public static void main(String[] args) {
        SpringApplication.run(TestApp.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        //do something
       van.fight();
    }
}

De plus, essayez de fusionner les deux VanConfigA/B et mettez l'annotation ConditionalOnClass sur la méthode. Si vous supprimez un package, une erreur se produira.

@ConditionalOnExpress

Jugement conditionnel basé sur des expressions. Cette fonction peut être utilisée dans la plupart des cas avec @ConditionalOnProperty L'expression est plus flexible car SpEL peut être utilisée. Dans l'exemple, la valeur de test.enabled dans les propriétés sera jugée. BeanConfig juge respectivement trois types de booléens, de chaînes et de nombres. J'ai essayé de nombreuses autres méthodes mais aucune ne fonctionne, comme l'utilisation directe de ==. Il semble que les attributs configurés seront traités comme des chaînes.

@Data
public class TestBean {
    private String name;
}
@Configuration
@ConditionalOnExpression("#{${test.enabled:true} }")
//@ConditionalOnExpression("'zz'.equalsIgnoreCase('${test.name2}')")
//@ConditionalOnExpression("new Integer('${test.account}')==1")
public class BeanConfig {
    @Bean
    public TestBean testBean(){
        return new TestBean("我是美猴王");
    }
}
@SpringBootApplication
public class TestAppCommand implements CommandLineRunner {
    @Autowired
    private TestBean testBean;

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

    @Override
    public void run(String... args) throws Exception {
        System.out.println(testBean.getName());
    }
}

@ConditionalOnProperty

convient au jugement conditionnel sur une seule propriété, tandis que le @ConditionalOnExpress ci-dessus convient à des situations plus complexes, telles que l'association de plusieurs propriétés Comparez. Cet exemple donne également trois types de base de jugements conditionnels, mais il semble qu'ils puissent tous être traités comme des chaînes...

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestBean {
    private String name;
}
@Configuration
@ConditionalOnProperty(prefix = "test", name="enabled", havingValue = "true",matchIfMissing = false)
//@ConditionalOnProperty(prefix = "test", name="account", havingValue = "1",matchIfMissing = false)
//@ConditionalOnProperty(prefix = "test", name="name1", havingValue = "zz",matchIfMissing = false)
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean("我是美猴王");
    }
}
@SpringBootApplication
public class TestAppCommand implements CommandLineRunner {
    @Autowired
    private TestBean testBean;
    public static void main(String[] args) {
        SpringApplication.run(TestAppCommand.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        System.out.println(testBean.getName());

    }
}

@ConditionalOnJava

Vous pouvez utilisez la version Java pour juger.

@Data
public class TestBean {
}
@Configuration
@ConditionalOnJava(JavaVersion.EIGHT)
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
    @Test
    public void test(){
        Map<string> map = context.getBeansOfType(TestBean.class);
        System.out.println(map);
    }
}</string>

@ConditionalOnResource

Effectuer un jugement conditionnel selon que le fichier de ressources spécifié existe, par exemple en jugeant ehcache.properties pour déterminer s'il faut assembler automatiquement le composant ehcache .

@Data
public class TestBean {
}
@Configuration
@ConditionalOnResource(resources = "classpath:application.yml")
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);

    @Test
    public void test(){
        Map<string> map = context.getBeansOfType(TestBean.class);
        System.out.println(map);
    }
}</string>

@ConditionalOnSingleCandidate

Je n'ai pas encore pensé au scénario d'application. Les conditions pour réussir la condition sont : 1. Il n'y a qu'un seul bean correspondant. conteneur 2. Le bean correspondant a Multiple, mais PRIMARY a été formulé. Dans l'exemple, lors de l'assemblage de BeanB, vous devez vérifier l'état de l'assemblage de BeanA, donc BeanBConfig doit être classé après BeanAConfig. Vous pouvez modifier BeanAConfig et supprimer l'annotation @Primary, ou supprimer les trois annotations @Bean, et BeanB ne le sera pas. instancié.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BeanA {
    private String name;
}
@Configuration
public class BeanAConfig {

    @Bean
    @Primary
    public BeanA bean1(){
        return new BeanA("bean1");
    }
    @Bean(autowireCandidate = false)
    public BeanA bean2(){
        return new BeanA("bean2");
    }
    //@Bean(autowireCandidate = false)
    public BeanA bean3(){
        return new BeanA("bean3");
    }
}
@Data
public class BeanB {
}
@Configuration
@AutoConfigureAfter(BeanAConfig.class)
@ConditionalOnSingleCandidate(BeanA.class)
public class BeanBConfig {

    @Bean
    public BeanB targetBean(){
        return new BeanB();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanAConfig.class, BeanBConfig.class);

    @Test
    public void test(){
        Map<string> map = context.getBeansOfType(BeanA.class);
        System.out.println(map);
        Map<string> map2 = context.getBeansOfType(BeanB.class);
        System.out.println(map2);
    }
}</string></string>

@ConditionalOnNotWebApplication & @ConditionalOnWebApplication

Déterminez si l'environnement actuel est une application Web.







Ces conditions dans le jugement Spring Boot



                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

Ces conditions dans Spring BootSpring Boot nous offre une multitude de conditions pour nous permettre de les utiliser très facilement dans le projet Ajouter des beans au conteneur. Cet article explique principalement chaque annotation et illustre son utilisation avec du code. Toutes les annotations ConditionalOnXXX peuvent être placées sur une classe ou une méthode. Si la méthode est sur une classe, elle déterminera si toutes les méthodes annotées @Bean de la classe sont exécutées. @ConditionalLes autres annotations conditionnelles ci-dessous sont du sucre syntaxique. Vous pouvez personnaliser ConditionalOnXXX via la méthode suivante.

L'interface Condition n'a qu'une seule méthode matches, qui renvoie le résultat de la correspondance.

Configurez les conditions via le système d'exploitation pour configurer Bean. Lorsque Window est utilisé, l'objet Person de Bill est instancié, et lorsque Linux est utilisé, l'objet Person de Linus est instancié.

Résultat de sortie :

Le système actuel est : Mac OS X
{linus=Person(name=Linus, age=48)}

public @interface Conditional {
    Class extends Condition>[] value();
}
@ConditionalOnBean & @ConditionalOnMissingBean

Ces deux annotations jugeront l'objet Bean dans le conteneur Bean. L'exemple utilisé est lors de la configuration s'il s'avère qu'il n'y en a pas. Instance d'ordinateur, instanciez un ordinateur de sauvegarde.
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

//LinuxCondition,为方便起见,去掉判断代码,直接返回true了
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        return true;
    }
}
//WindowsCondition,为方便起见,去掉判断代码,直接返回false了
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
        return false;
    }
}
Modifiez BeanConfig, si vous commentez le premier @Bean, l'ordinateur de sauvegarde sera instancié, sinon l'ordinateur de sauvegarde ne sera pas instancié
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
//配置类
@Configuration
public class BeanConfig {

    @Bean(name = "bill")
    @Conditional({WindowsCondition.class})
    public Person person1(){
        return new Person("Bill Gates",62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person2(){
        return new Person("Linus",48);
    }
}
@ConditionalOnClass & @ConditionalOnMissingClass
public class AppTest {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);

    @Test
    public void test(){
        String osName = applicationContext.getEnvironment().getProperty("os.name");
        System.out.println("当前系统为:" + osName);
        Map<string> map = applicationContext.getBeansOfType(Person.class);
        System.out.println(map);
    }
}</string>

Cette annotation déterminera s'il y a une classe spécifiée sur le chemin de classe. J'étais confus lorsque je l'ai vue pour la première fois. S'il n'y a pas de classe spécifiée sur le chemin de classe, la compilation ne réussira pas. .. Ceci est principalement utilisé lors de l'intégration de composants tiers avec la même fonction. Tant qu'il y a une classe du composant sur le chemin de classe, elle sera automatiquement configurée. Par exemple, lorsque Spring Boot Web configure automatiquement le. composant view, qu'il utilise Velocity, Thymeleaf ou freemaker, c'est la méthode utilisée.

L'exemple est deux ensembles d'armures A (combinaison légère) et B (combinaison sombre). Si A n'est pas présent, configurez B.

Van est un samouraï et utilise la combinaison pour combattre

VanConfigA/B instancie le samouraï

@Data
@AllArgsConstructor
@ToString
public class Computer {
    private String name;
}
@Configuration
public class BeanConfig {
    @Bean(name = "notebookPC")
    public Computer computer1(){
        return new Computer("笔记本电脑");
    }

    @ConditionalOnMissingBean(Computer.class)
    @Bean("reservePC")
    public Computer computer2(){
        return new Computer("备用电脑");
    }
}
Classe de test, par défaut, si suit AB Les deux sont sur le chemin de classe, les deux ensembles seront chargés et A sera défini sur PRIMARY. Si FightA.class est supprimé dans la classe cible, seul l'ensemble B sera chargé.
public class TestApp {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
    @Test
    public void test1(){
        Map<string> map = applicationContext.getBeansOfType(Computer.class);
        System.out.println(map);
    }
}</string>

De plus, essayez de fusionner les deux VanConfigA/B et mettez l'annotation ConditionalOnClass sur la méthode. Si vous supprimez un package, une erreur se produira.

@ConditionalOnExpress


Jugement conditionnel basé sur des expressions. Cette fonction peut être utilisée dans la plupart des cas avec @ConditionalOnProperty L'expression est plus flexible car SpEL peut être utilisée. Dans l'exemple, la valeur de test.enabled dans les propriétés sera jugée. BeanConfig juge respectivement trois types de booléens, de chaînes et de nombres. J'ai essayé de nombreuses autres méthodes mais aucune ne fonctionne, comme l'utilisation directe de ==. Il semble que les attributs configurés seront traités comme des chaînes.

public interface Fighter {
    void fight();
}
public class FighterA implements Fighter {
    @Override
    public void fight() {
        System.out.println("使用光明套装");
    }
}
public class FighterB implements Fighter {
    @Override
    public void fight() {
        System.out.println("使用暗黑套装");
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Van {
    private Fighter fighter;
    public void fight(){
        fighter.fight();
    }
}
@ConditionalOnProperty

convient au jugement conditionnel sur une seule propriété, tandis que le @ConditionalOnExpress ci-dessus convient à des situations plus complexes, telles que l'association de plusieurs propriétés Comparez. Cet exemple donne également trois types de base de jugements conditionnels, mais il semble qu'ils puissent tous être traités comme des chaînes...
@Configuration
@ConditionalOnClass({FighterA.class})
public class VanConfigA {
    @Primary
    @Bean
    public Van vanA(){
        return new Van(new FighterA());
    }
}
@Configuration
@ConditionalOnClass({FighterB.class})
public class VanConfigB {
    @Bean
    public Van vanB(){
        return new Van(new FighterB());
    }
}

@SpringBootApplication
public class TestApp implements CommandLineRunner {
    @Autowired
    private Van van;
    public static void main(String[] args) {
        SpringApplication.run(TestApp.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        //do something
       van.fight();
    }
}

@ConditionalOnJava

Vous pouvez utilisez la version Java pour juger.

@Data
public class TestBean {
    private String name;
}
@Configuration
@ConditionalOnExpression("#{${test.enabled:true} }")
//@ConditionalOnExpression("'zz'.equalsIgnoreCase('${test.name2}')")
//@ConditionalOnExpression("new Integer('${test.account}')==1")
public class BeanConfig {
    @Bean
    public TestBean testBean(){
        return new TestBean("我是美猴王");
    }
}
@ConditionalOnResource
@SpringBootApplication
public class TestAppCommand implements CommandLineRunner {
    @Autowired
    private TestBean testBean;

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

    @Override
    public void run(String... args) throws Exception {
        System.out.println(testBean.getName());
    }
}

Effectuer un jugement conditionnel selon que le fichier de ressources spécifié existe, par exemple en jugeant ehcache.properties pour déterminer s'il faut assembler automatiquement le composant ehcache .

@Data
public class TestBean {
}
@Configuration
@ConditionalOnResource(resources = "classpath:application.yml")
public class BeanConfig {

    @Bean
    public TestBean testBean(){
        return new TestBean();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);

    @Test
    public void test(){
        Map<string> map = context.getBeansOfType(TestBean.class);
        System.out.println(map);
    }
}</string>

@ConditionalOnSingleCandidate

这个还没有想到应用场景,条件通过的条件是:1 对应的bean容器中只有一个 2.对应的bean有多个,但是已经制定了PRIMARY。例子中,BeanB装配的时候需要看BeanA的装配情况,所以BeanBConfig要排在BeanAConfig之后.可以修改BeanAConfig,将@Primary注解去掉,或者把三个@Bean注解去掉,BeanB就不会实例化了。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BeanA {
    private String name;
}
@Configuration
public class BeanAConfig {

    @Bean
    @Primary
    public BeanA bean1(){
        return new BeanA("bean1");
    }
    @Bean(autowireCandidate = false)
    public BeanA bean2(){
        return new BeanA("bean2");
    }
    //@Bean(autowireCandidate = false)
    public BeanA bean3(){
        return new BeanA("bean3");
    }
}
@Data
public class BeanB {
}
@Configuration
@AutoConfigureAfter(BeanAConfig.class)
@ConditionalOnSingleCandidate(BeanA.class)
public class BeanBConfig {

    @Bean
    public BeanB targetBean(){
        return new BeanB();
    }
}
public class TestApp {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanAConfig.class, BeanBConfig.class);

    @Test
    public void test(){
        Map<string> map = context.getBeansOfType(BeanA.class);
        System.out.println(map);
        Map<string> map2 = context.getBeansOfType(BeanB.class);
        System.out.println(map2);
    }
}</string></string>

@ConditionalOnNotWebApplication & @ConditionalOnWebApplication

判断当前环境是否是Web应用。

  • Introduction au jugement conditionnel dans Spring Boot (avec code)


你可能感兴趣的



评论                                                    



载入中...

显示更多评论


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer