上篇文章我们主要讲了spring自动装配的原理,我们知道了springboot在启动的时候会自动去读.factories文件,在factories文件中,autoConfiguration对应的就是我们程序启动时自己预加载的类,另外我也提到了另外一个比较核心的注解,即@ConditionOnxxx。详情点击https://blog.csdn.net/qq_41907991/article/details/88704448


这篇文章我们主要分析下@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();
}
}

我们在测试项目中加了配置信息

config.name=zhangsan

运行结果如下:

  '  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: 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

最新文章

  1. Manthan, Codefest 16(B--A Trivial Problem)
  2. Markdown 简明语法手册
  3. iOS音频AAC视频H264编码 推流最佳方案
  4. ajax是异步的,异步取数据,如何能保证数据是存在的。
  5. tp_link路由器 重新设置
  6. 11Mybatis_mybatis开发Dao的方法
  7. 【Apache运维基础(5)】Apache的Rewrite攻略(2)
  8. VC++2010配置使用MySQL5.6
  9. WEB网站常见受攻击方式及解决办法
  10. iis最大连接数和队列长度
  11. ng-view和ng-include之间的区别
  12. Java并发编程:sleep、wait、yield对比
  13. PID控制算法研究
  14. Oracle的安装问题
  15. python 项目中的 requirements.txt
  16. DAX/PowerBI系列 - 库存总价值(Inventory Value)
  17. SAP ABAP 查找用户出口
  18. AngularJS中Scope间通讯Demo
  19. Bean的加载过程
  20. shell 使用变量

热门文章

  1. 第十节:xml、re、logging模块
  2. 使用 Chrome 插件 Vimium 打造黑客浏览器
  3. matlab计算LZ复杂度
  4. stand up meeting 1/12/2016
  5. 常用App用户体验找茬
  6. vue2.x学习笔记(二十一)
  7. JSP中引用CSS样式文件却无法显示的问题解决方案
  8. s3cmd s3命令行工具
  9. Java面试系列第2篇-Object类中的方法
  10. TensorFlow的模型保存与加载