SpringBoot自动配置原理:
1. Condition接口:
Condition接口是spring4.0之后提供的接口,增加条件判断功能,用于选择性的创建Bean对象到spring容器中。
在Condition接口有一个方法:matches(),该方法用于判断,当加入了相关坐标依赖后,返回值为true,没有加入依赖,
则返回值为false。
2.相关注解说明:
@Configuration:标记该类是一个配置类
@Bean:用在方法上,将方法的返回值(一般是Bean)注册给spring容器管理
@Conditional(OnCondition.class):用在方法上,用于判断,如果类OnCondition中的方法matches()返回值为true,
则执行下面的代码,否则不执行
@Import:
import注解用于导入其他的配置,让spring容器进行加载和初始化。import的注解有以下的几种方式使用:
1. @Import(User.class):
直接导入Bean,注意使用该注解,类User要使用注解@Component注册给spring容器;
2. @Import(UserConfig.class):
3. @Import(MyImportSelector.class):导入ImportSelector接口的实现类,实现类中重写方法selectImports(),
该方法返回要注册到spring容器中的Bean的全路径,即:
return new String[]{"com.itheima.pojo.Role", "com.itheima.pojo.User"};
4. @Import(MyImportBeanDefinitionRegistrar.class):导入ImportBeanDefinitionRegistrar实现类,重写
registerBeanDefinitions()方法:
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//创建BeanDefiniation
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
//注册bean 目前只注册User
registry.registerBeanDefinition("user",beanDefinition);
}
@SpringBootApplication:
该注解由以下三个注解所组成:
1. @SpringbootConfiguration:
该注解等价于@Configuration,用于标记该类是一个配置类;
2. @ComponentScan:
该注解用于组件扫描(包扫描),类似于xml中的context-componet-scan,如果不指定扫描路径,
那么就扫描该注解修饰的启动类所在的包以及子包。
3. @EnableAutoConfiguration
1.组合了@import注解,导入配置
2.使用了@Import的第三种用法,导入ImportSelector接口的实现类,selectImports导入类中的方法中加载配置返回Bean定义的字符数组
3.加载META-INF/spring.factories ,获取Bean定义的全路径名返回
4.最终返回回去即可
需求:
当加入了jedis依赖后,自动创建User存入spring容器中;没有jedis依赖坐标,则不创建User;
实现:
1. 创建工程,导入坐标:
<?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.it</groupId>
<artifactId>springboot-condition</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<!--加入springboot的starter起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
</project>
2. 创建pojo--User
package com.it.pojo;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/1
*/
public class User {
}
3. 创建启动类
package com.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/1
*/
@SpringBootApplication
public class ConditionApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ConditionApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
4. 创建配置类,用于向spring容器中注册对象:
package com.it.config;
import com.it.condition.OnCondition;
import com.it.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/1
*/
@Configuration//标记该类是一个配置类
public class UserConfig {
//注册Bean--User交给spring来管理
//当导入了相关坐标依赖的时候
@Bean
@Conditional(OnCondition.class)//用于判断,如果OnCondition中的matches()返回值为true,则执行下面的代码,否则不执行
public User user(){//注意方法名不能改
return new User();
}
}
5. 创建类OnCondition,用于判断
package com.it.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/1
*/
public class OnCondition implements Condition {
//用于判断,符合条件,返回true,不符合条件,返回false
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//jedis坐标存在,返回true
try {
Class.forName("redis.clients.jedis.Jedis");//执行成功,说明类加载到了,类存在
} catch (ClassNotFoundException e) {//否则,说明类不存在
e.printStackTrace();
return false;
}
//jedis坐标不存在,返回false
return true;
}
}
3. 切换内置的web容器Tomcat
1. 排除Tomcat的起步依赖:
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
2. 加入其它web容器的依赖:例如:jetty,netty等
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>