이 기사에서는 Spring Boot의 조건부 판단(코드 포함)에 대해 소개합니다. 필요한 참고가 될 수 있는 내용이길 바랍니다.
Spring Boot의 조건부
spring boot는 프로젝트의 컨테이너에 빈을 매우 편리하게 추가할 수 있는 풍부한 조건부 세트를 제공합니다. 이 문서에서는 주로 각 주석을 설명하고 코드와 함께 사용하는 방법을 보여줍니다.
모든 ConditionalOnXXX 주석은 클래스 또는 메서드에 배치될 수 있습니다. 메서드가 클래스에 있는 경우 클래스의 모든 @Bean 주석이 달린 메서드가 실행되는지 여부를 결정합니다.
아래의 다른 조건부 주석은 다음 방법을 통해 ConditionalOnXXX를 사용자 정의할 수 있으며, Conditional 인터페이스를 구현하는 클래스 배열을 받습니다.
public @interface Conditional { Class extends Condition>[] value(); }
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; } }
@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>
@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>로그인 후 복사로그인 후 복사
BeanConfig를 수정하세요. 첫 번째 @Bean을 주석 처리하면 백업 컴퓨터가 인스턴스화되고, 그렇지 않으면 백업 컴퓨터가 인스턴스화되지 않습니다.
이 주석은 지정된 클래스가 있는지 확인합니다. 클래스 경로 , 처음 봤을 때 헷갈렸는데, 클래스 경로에 지정된 클래스가 없으면 컴파일이 통과되지 않습니다... 이는 주로 동일한 기능을 가진 타사 구성 요소를 통합하는 데 사용됩니다. 클래스 경로에 컴포넌트가 있으므로 자동 구성이 수행됩니다. 예를 들어 Spring Boot 웹에서는 Velocity, Thymeleaf 또는 freemaker를 사용하여 뷰 구성 요소를 자동으로 구성할 때 이 방법을 사용합니다.
예는 갑옷 A(라이트 슈트)와 B(다크 슈트) 2세트입니다. A가 없으면 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("使用暗黑套装"); } }
@Data @AllArgsConstructor @NoArgsConstructor public class Van { private Fighter fighter; public void fight(){ fighter.fight(); } }
@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(); } }
또한 두 개의 VanConfigA/B를 병합하고 메서드에 ConditionalOnClass 주석을 추가해 보세요. 패키지를 삭제하면 오류가 발생합니다.
@ConditionalOnExpress
이 함수는 대부분의 경우 @ConditionalOnProperty와 함께 사용할 수 있습니다. SpEL을 사용할 수 있으므로 표현식이 더 유연해집니다. 예제에서는 속성의 test.enabled 값을 판단합니다. BeanConfig는 각각 Boolean, string, number 세 가지 유형을 판단합니다. 다른 많은 방법을 시도했지만 ==를 직접 사용하는 등 아무것도 작동하지 않습니다. 구성된 속성이 문자열로 처리되는 것 같습니다.
@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
@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
@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
@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
@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
~ ~ O oSpring Boot의 Conditional
spring Boot는 풍부한 조건부를 제공하여 프로젝트의 컨테이너에 Bean을 추가하는 데 매우 편리합니다. 이 문서에서는 주로 각 주석을 설명하고 코드와 함께 사용하는 방법을 보여줍니다. 모든 ConditionalOnXXX 주석은 클래스 또는 메서드에 배치될 수 있습니다. 메서드가 클래스에 있는 경우 클래스의 모든 @Bean 주석이 달린 메서드가 실행되는지 여부를 결정합니다. @Conditional아래의 다른 조건부 주석은 다음 방법을 통해 ConditionalOnXXX를 사용자 정의할 수 있으며, Conditional 인터페이스를 구현하는 클래스 배열을 받습니다. public @interface Conditional {
Class extends Condition>[] value();
}
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;
}
}
@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>
현재 시스템은 다음과 같습니다. Mac OS Bean 개체는 구성 중에 사용됩니다. 컴퓨터 인스턴스가 없는 것으로 확인되면 백업 컴퓨터가 인스턴스화됩니다.
@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>
@ConditionalOnClass & @ConditionalOnMissingClass
이 주석은 지정된 클래스가 있는지 확인합니다. 클래스 경로 , 처음 봤을 때 헷갈렸는데, 클래스 경로에 지정된 클래스가 없으면 컴파일이 통과되지 않습니다... 이는 주로 동일한 기능을 가진 타사 구성 요소를 통합하는 데 사용됩니다. 클래스 경로에 컴포넌트가 있으므로 자동 구성이 수행됩니다. 예를 들어 Spring Boot 웹에서는 Velocity, Thymeleaf 또는 freemaker를 사용하여 뷰 구성 요소를 자동으로 구성할 때 이 방법을 사용합니다.
예는 갑옷 A(라이트 슈트)와 B(다크 슈트) 2세트입니다. A가 없으면 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("使用暗黑套装"); } }
@Data @AllArgsConstructor @NoArgsConstructor public class Van { private Fighter fighter; public void fight(){ fighter.fight(); } }
@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(); } }
또한 두 개의 VanConfigA/B를 병합하고 메서드에 ConditionalOnClass 주석을 추가해 보세요. 패키지를 삭제하면 오류가 발생합니다.
@ConditionalOnExpress
이 함수는 대부분의 경우 @ConditionalOnProperty와 함께 사용할 수 있습니다. SpEL을 사용할 수 있기 때문에 표현식이 더 유연해집니다. 예제에서는 속성의 test.enabled 값을 판단합니다. BeanConfig는 각각 Boolean, string, number 세 가지 유형을 판단합니다. 다른 많은 방법을 시도했지만 ==를 직접 사용하는 등 아무것도 작동하지 않습니다. 구성된 속성이 문자열로 처리되는 것 같습니다.
@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는 단일 속성에 대한 조건부 판단에 적합한 반면, 위의 @ConditionalOnExpress는 여러 속성의 연관 비교와 같은 보다 복잡한 상황에 적합합니다. 이번 예시도 기본 조건부 판단 3가지를 제시하고 있는데 모두 문자열로 처리할 수 있을 것 같네요...
@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()); } }
@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>
@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>
这个还没有想到应用场景,条件通过的条件是: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>
判断当前环境是否是Web应用。
评论
위 내용은 Spring Boot의 조건부 판단 소개(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!