1、通过实现Condition接口和添加Conditional注解实现springboot的自动装配
有时候我们需要根据条件自动装配一些bean,比如根据当前运行的文件是utf-8还是gbk编码来绝定装配哪个bean,请看下面示例,装配了utf8的bean
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.edu.spring</groupId> <artifactId>springboot</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>springboot</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.6.RELEASE</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> </project>
EncodingConvert.java,接口
package com.edu.spring.springboot; public interface EncodingConvert { }
GBKEncodingConvert.java,实现类1
package com.edu.spring.springboot; public class GBKEncodingConvert implements EncodingConvert { }
UTF8EncodingConvert.java,实现类2
package com.edu.spring.springboot; public class UTF8EncodingConvert implements EncodingConvert { }
GBKCondition.java,实现Condition接口
package com.edu.spring.springboot; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class GBKCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // TODO Auto-generated method stub String encoding=System.getProperty("file.encoding"); if(encoding!=null){ return "gbk".equals(encoding.toLowerCase()); } return false; } }
UTF8Condition.java,实现Condition接口
package com.edu.spring.springboot; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class UTF8Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // TODO Auto-generated method stub String encoding=System.getProperty("file.encoding"); if(encoding!=null){ return "utf-8".equals(encoding.toLowerCase()); } return false; } }
EncodingConvertConfig.java,创建bean
package com.edu.spring.springboot; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @SpringBootConfiguration public class EncodingConvertConfig { @Bean @Conditional(UTF8Condition.class) public EncodingConvert createUTF8EncodingConvert(){ return new UTF8EncodingConvert(); } @Bean @Conditional(GBKCondition.class) public EncodingConvert createGBKEncodingConvert(){ return new GBKEncodingConvert(); } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBeansOfType(EncodingConvert.class)); context.close(); } }
运行结果如下:
总结:@Conditional注解与Condition接口要一块使用,Condition接口实现类中的matches方法返回true时,@Conditional标记的bean才会装配。
@Conditional注解可以加在配置类上,表明该配置类中装配的bean都需要满足返回true的条件。
@Conditional注解可以添加多个类,表明要同时满足多个条件才会装配,如@Conditional({UTF8Condition.class,GBKCondition.class})。
2、Conditional的一些默认实现注解
(1)@ConditionalOnProperty:根据配置文件中的属性装配bean。如下,配置文件中存在runnable.enble,且值为true时装配
application.properties
runnable.enble=true
UserConfig.java
package com.edu.spring.springboot; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @SpringBootConfiguration public class UserConfig { @Bean @ConditionalOnProperty(name="runnable.enble",havingValue="true") public Runnable createRunnable (){ return () -> {}; } }
App.java
package com.edu.spring.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main( String[] args ) { ConfigurableApplicationContext context=SpringApplication.run(App.class,args); System.out.println(context.getBeansOfType(Runnable.class)); context.close(); } }
运行结果如下:
说明:如果改为runnable.enble=false,或者删掉该配置,再次运行则不会创建bean。添加matchIfMissing=true,即便是属性不存在,运行也会创建bean
(2)@ConditionalOnClass:classpath路径中存在指定的类则创建bean,如下:
pom.xml,添加gson的依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.edu.spring</groupId> <artifactId>springboot</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>springboot</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.6.RELEASE</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> </dependencies> </project>
UserConfig.java
package com.edu.spring.springboot; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @SpringBootConfiguration public class UserConfig { @Bean @ConditionalOnClass(name="com.google.gson.Gson") public Runnable createRunnable(){ return () -> {}; } }
运行结果如下:
创建成功,如果删掉依赖则不会创建。
(3)@ConditionalOnBean:如果某个bean存在时,则创建bean,如下:
UserConfig.java
package com.edu.spring.springboot; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; @SpringBootConfiguration public class UserConfig { @Bean @ConditionalOnBean(name="user") public Runnable createRunnable3(){ return () -> {}; } }
运行如下:不会创建bean
User.java,创建user
package com.edu.spring.springboot; import org.springframework.stereotype.Component; @Component public class User { }
再次运行,创建成,结果如下:
(4)@ConditionalOnMissingBean:当bean不存在时创建,与ConditionalOnBean相反。