这篇文章我们主要分析下@ConditionOnxxx注解,以及自己实现一个starter。下面开始分析我们的@ConditionOnxxx注解。先看代码:
我们以@ConditionalOnMissingBean这个注解来分析原理:
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnMissingBean {....}
很明显,上面的核心注解就是@Conditional注解,我们接下来分析这个注解,直接上代码看效果
package com.study.spring.condition.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; /** * @Author: dmz * @Description: * @Date: Create in 23:16 2019/3/25 */ public class CatCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return context.getEnvironment().getProperty("what").equals("cat"); } }
package com.study.spring.condition.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; /** * @Author: dmz * @Description: * @Date: Create in 23:16 2019/3/25 */ public class DogCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return context.getEnvironment().getProperty("what").equals("dog"); } }
上面这两个类,是我自定义的两个条件
package com.study.spring.condition.model; import com.study.spring.condition.condition.CatCondition; import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Component; /** * @Author: dmz * @Description: * @Date: Create in 23:19 2019/3/25 */ @Component @Conditional({CatCondition.class}) public class Cat { public Cat(){ System.out.println("猫来了,喵喵喵~~"); } }
package com.study.spring.condition.model; import com.study.spring.condition.condition.DogCondition; import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Component; /** * @Author: dmz * @Description: * @Date: Create in 23:18 2019/3/25 */ @Component @Conditional({DogCondition.class}) public class Dog { public Dog(){ System.out.println("dog 来了,汪汪汪~~~"); } }
主要是为了通过条件控制我们这两个类的加载
what:cat
这是配置文件中的内容
package com.study.spring.condition; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConditionApplication { public static void main(String[] args) { SpringApplication.run(ConditionApplication.class, args); } }
这是启动类
启动程序,可以看到程序打印:
经过上面的程序我相信大家对这个@conditional注解已经有了一定的了解
接下来我们来实现我们的自定义starter
pom文件如下:
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.study.spring</groupId> <artifactId>starter</artifactId> <version>0.0.1-SNAPSHOT</version> <name>myAutoconfig-spring-boot-starter</name> <description>Demo project for Spring Boot</description> <packaging>jar</packaging> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <!--为了生成spring-configuration-metadata.json--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
整体项目结构如下
package com.study.spring.starter.AutoConfig; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author dmz * @date Create in 22:06 2019/3/23 */ @Data @ConfigurationProperties(prefix = "config") public class Config { private String name; private Integer age; }
package com.study.spring.starter.AutoConfig; import com.study.spring.starter.service.MyService; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author dmz * @date Create in 21:24 2019/3/23 */ @Configuration @EnableConfigurationProperties(Config.class) @ConditionalOnClass(MyService.class) public class MyAutoConfig { @Bean @ConditionalOnMissingBean(MyService.class) public MyService getMyService() { return new MyService(); } }
package com.study.spring.starter.service; import com.study.spring.starter.AutoConfig.Config; import org.springframework.beans.factory.annotation.Autowired; /** * @author dmz * @date Create in 21:53 2019/3/23 */ public class MyService { @Autowired private Config config; public void say() { System.out.println("自定义的starter来了,say:" + config.getName()); } }
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** *保留启动类,主要是为了执行maven的命令, * 打包到我们的本地仓库 */ @SpringBootApplication public class StarterApplication{ public static void main(String[] args) { SpringApplication.run(StarterApplication.class, args); } }
spring.factories文件如下
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.study.spring.starter.AutoConfig.MyAutoConfig
测试代码如下:
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.study.spring</groupId> <artifactId>starter-test</artifactId> <version>0.0.1-SNAPSHOT</version> <name>starter-test</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--引入我们的依赖--> <dependency> <groupId>com.study.spring</groupId> <artifactId>starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
启动类:
package com.study.spring.startertest; import com.study.spring.starter.service.MyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class StarterTestApplication implements ApplicationRunner { @Autowired private MyService myService; public static void main(String[] args) { SpringApplication.run(StarterTestApplication.class, args); } @Override public void run(ApplicationArguments args) throws Exception { myService.say(); } }
我们在测试项目中加了配置信息
运行结果如下:
' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) 2019-03-27 00:09:52.995 INFO 19468 --- [ main] c.s.s.s.StarterTestApplication : Starting StarterTestApplication on DESKTOP-N88SU6M with PID 19468 (C:\Users\dell\Desktop\spring-master\starter-test\target\classes started by dell in C:\Users\dell\Desktop\spring-master) 2019-03-27 00:09:52.999 INFO 19468 --- [ main] c.s.s.s.StarterTestApplication : No active profile set, falling back to default profiles: default 2019-03-27 00:09:53.416 INFO 19468 --- [ main] c.s.s.s.StarterTestApplication : Started StarterTestApplication in 0.722 seconds (JVM running for 1.243) 自定义的starter来了,say:zhangsan Process finished with exit code 0
验证成功
项目github地址:https://github.com/daimingzhi/spring.git