@ConditionalOnClass的编译问题,用示例让你明白!

文章探讨了如何在SpringBoot中使用@ConditionalOnClass注解进行条件性配置,以及如何通过Maven的optional标签管理依赖,确保即使类不存在也能通过编译,同时实现代理自动配置的功能。
摘要由CSDN通过智能技术生成

问题

在学习@ConditionalOnClass注解时,我有个百思不得其解的问题,如以下内容

package com.example.child.config;

import com.example.parent.model.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(value = Test.class)
public class TestConfig {
    public TestConfig() {
        System.out.println("config实例化");
    }
}

在这里插入图片描述

现在类路径中没有Test这个类,那肯定编译都通不过,所以@Test(value = {Test.class})那肯定需要有Test类,那么Test类肯定在类路径下,一旦有Test类,TestConfig肯定被实例化,那这么配置有什么意义,你是不是有这个疑问?

其实就是通过maven的一些配置让包能通过编译,实际上不让文件进入包中。

spring中的应用

在这里插入图片描述

spring中如何做到这种项目中没有SecurityEvaluationContextExtension类,但是却通过编译的。

我看看一看spring-boot的依赖关系
在这里插入图片描述
在这里插入图片描述
其实就是通过maven配置optional达到的效果,optional允许我们将某些依赖项声明为可选。了解optional可以看看我的另一篇文章,optional详解

示例

我建了三个项目,分别为parent-maven,maven-child,springTest来实践@ConditionalOnClass怎么做到自动配置。

parent-maven

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>parent-maven</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>parent-maven</name>
    <description>parent-maven</description>
    <properties>
        <java.version>8</java.version>
    </properties>
     <dependencies>
    </dependencies>
</project>

Test代码

package com.example.parent.model;

public class Test {
    public Test() {
        System.out.println("Test实例化");
    }
}

该项目中新建了一个Test类,pom文件中什么依赖都没引入。

打包

在这里插入图片描述

安装到maven仓库

maven-child

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

pom文件

parent-mavenparent-maven<optional>true</optional><?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>maven-child</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>maven-child</name>
    <description>maven-child</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>parent-maven</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

<optional>true</optional>这一句特别重要,将parent-maven设置为可选的。

TestConfig代码

package com.example.child.config;

import com.example.parent.model.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(value = Test.class)
public class TestConfig {
    public TestConfig() {
        System.out.println("config实例化");
    }
}

TestConfig是我的配置文件类,我想的是当我类路径下有Test时我就加载这个配置文件,没有时我就不加载,当然这个项目时会被打包为一个jar供别的项目使用。

打包

在这里插入图片描述

安装到maven仓库

springTest

现在就是重点,我想动态的去加载TestConfig配置文件,当引入依赖时就去配置,像spring的很多自动配置一样。

springTest是一个springBoot项目。

在这里插入图片描述

pom文件

maven-childmaven-child<?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 https://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.2.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>springTest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springTest</name>
	<description>springTest</description>
	<properties>
		<java.version>8</java.version>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<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.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.1</version>
		</dependency>
		<dependency>
			<groupId>com.github.shyiko</groupId>
			<artifactId>mysql-binlog-connector-java</artifactId>
			<version>0.21.0</version>
		</dependency>
		<dependency>
			<groupId>com.example</groupId>
			<artifactId>maven-child</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>

	<build>

		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

我现在引入了maven-child依赖,该依赖中有TestConfig配置文件,当类路径中有Test类时会自动配置。

在这里插入图片描述

启动spring

在这里插入图片描述

从图中没有看到打印“config实例化”,所以TestConfig配置类没有被加载。

注意:spring启动时需要需要扫到TestConfig类,这点很重要。
在这里插入图片描述

现在我想要自动配置怎么办,这是我们就得显示的加上 parent-maven依赖。

在这里插入图片描述
在这里插入图片描述
在启动spring
在这里插入图片描述
成功加载配置文件,spring很多自动配置就是这样做的,都看到这儿点个赞再走吧。

  • 18
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值