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

问题

在学习@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实例化");
    }
}

@ConditionalOnClass的编译问题,用示例让你明白!_第1张图片

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

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

spring中的应用

@ConditionalOnClass的编译问题,用示例让你明白!_第2张图片

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

我看看一看spring-boot的依赖关系
@ConditionalOnClass的编译问题,用示例让你明白!_第3张图片
@ConditionalOnClass的编译问题,用示例让你明白!_第4张图片
其实就是通过maven配置optional达到的效果,optional允许我们将某些依赖项声明为可选。了解optional可以看看我的另一篇文章,optional详解

示例

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

parent-maven

@ConditionalOnClass的编译问题,用示例让你明白!_第5张图片

pom文件



    4.0.0
    com.example
    parent-maven
    0.0.1-SNAPSHOT
    parent-maven
    parent-maven
    
        8
    
     
    

Test代码

package com.example.parent.model;

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

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

打包

@ConditionalOnClass的编译问题,用示例让你明白!_第6张图片

安装到maven仓库

maven-child

@ConditionalOnClass的编译问题,用示例让你明白!_第7张图片

pom文件

parent-mavenparent-maventrue

    4.0.0
    com.example
    maven-child
    0.0.1-SNAPSHOT
    maven-child
    maven-child
    
        8
    
    
        
            org.springframework.boot
            spring-boot
            2.2.0.RELEASE
        
        
            org.springframework.boot
            spring-boot-test
            2.2.0.RELEASE
        
        
            com.example
            parent-maven
            0.0.1-SNAPSHOT
            true
        
        
            org.springframework.boot
            spring-boot-starter-actuator
            2.2.0.RELEASE
        
        
            org.springframework.boot
            spring-boot-autoconfigure
            2.2.0.RELEASE
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

true这一句特别重要,将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供别的项目使用。

打包

@ConditionalOnClass的编译问题,用示例让你明白!_第8张图片

安装到maven仓库

springTest

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

springTest是一个springBoot项目。

@ConditionalOnClass的编译问题,用示例让你明白!_第9张图片

pom文件

maven-childmaven-child

	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.2.0.RELEASE
		 
	
	com.example
	springTest
	0.0.1-SNAPSHOT
	springTest
	springTest
	
		8
		8
		8
	
	
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			2.1.1
		
		
			com.github.shyiko
			mysql-binlog-connector-java
			0.21.0
		
		
			com.example
			maven-child
			0.0.1-SNAPSHOT
		
	

	

		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	



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

@ConditionalOnClass的编译问题,用示例让你明白!_第10张图片

启动spring

@ConditionalOnClass的编译问题,用示例让你明白!_第11张图片

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

注意:spring启动时需要需要扫到TestConfig类,这点很重要。
@ConditionalOnClass的编译问题,用示例让你明白!_第12张图片

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

@ConditionalOnClass的编译问题,用示例让你明白!_第13张图片
@ConditionalOnClass的编译问题,用示例让你明白!_第14张图片
在启动spring
@ConditionalOnClass的编译问题,用示例让你明白!_第15张图片
成功加载配置文件,spring很多自动配置就是这样做的,都看到这儿点个赞再走吧。

你可能感兴趣的:(java,开发语言)