spring-boot系列
发布日期:2021-05-07 14:38:26 浏览次数:18 分类:技术文章

本文共 6912 字,大约阅读时间需要 23 分钟。

spring-boot系列


spring-boot自动配置


前言

本节主要讲Condition接口、切换内置服务器、@Enable*注解、@SpringBootApplication四个部分


在这里插入图片描述


一、Condition接口

1. 来历

Condition接口,是在spring4.0增加的条件判断功能,可以实现选择性的创建bean操作

2. 使用方法

@Conditional(ClassCondition.class),这个注解需要传递一个实现了Condition接口的class对象,

Condition接口只有一个boolean matches()方法,用此条件来判断这个bean是否创建

自定义注解@ConditionOnClass:    首先要继承@Conditional(ClassCondition.class),表明此注解是个衍生注解,    功能和@Conditional()完全一样,但是可以自己定义一个String[] value();    当其它类使用这个注解时,能够传入String数组,交给自定义的OnClassCondition类    使用,具体写法如下:
@Target({   ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Conditional(OnClassCondition.class)public @interface ConditionOnClass {       String[] value();}
自定义OnClassCondition:	metadata.getAnnotationAttributes(String annotationName).get("value")		方法能获取注解的value数组,这样可以将前面自定义的注解传入并获取	再将每个value进行判断来返回相应的布尔值,就可以实现不同条件是否创建bean本例是通过Class.forName(className);来判断传入的类是否存在,存在就返回true
public class OnClassCondition implements Condition {       @Override    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {           String[] classNames = (String[]) metadata.getAnnotationAttributes(ConditionOnClass.class.getName()).get("value");        for (String className : classNames) {               try {                   Class.forName(className);            } catch (ClassNotFoundException e) {                   return false;            }        }        return true;    }}
//至此,实现了必须存在这个对象才能创建这个bean    @ConditionOnClass("org.springframework.data.redis.core.RedisTemplate")    @Bean    public RedisTemplate redisTemplate(){           return new RedisTemplate();    }
在Maven:org.springframework.boot:spring-boot-autoconfigure中的condition包下,有一系列的ConditionOn*的注解,就是用来实现各种bean动态创建的,我们通常可以使用这些注解来决定bean是否创建

二、切换内置服务器

1.服务器切换

切换内置服务器jetty、undertow、netty,通过pom文件配置在Maven:org.springframework.boot:spring-boot-autoconfigure中的web包下的embedded包有四个web服务器,修改最后的名字就可以了
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
org.springframework.boot
spring-boot-starter-jetty

三、@Enable*注解

1.介绍

@Enable*注解,用于开启某些功能,底层是@import注解,实现bean的动态加载

2.@Import详解

@Import(xxx.class)注解能够将一个类xxx导入spring容器中,通常将其配置spring类上(例如@Configuration),作为导入bean的一种方式,此外,他还有两种方式,一是导入实现了ImportSelector接口的类,通过数组导入:	@Import(MyImportSelector.class)	二是导入实现ImportBeanDefinitionRegistrar接口的类,通过bean工厂注册:	@Import(MyImportBeanDefinitionRegistrar)以下是实现代码:	public class MyImportSelector implements ImportSelector {   		@Override		public String[] selectImports(AnnotationMetadata annotationMetadata) {   			return new String[]{   "com.lzb.other.bean.User","com.lzb.other.bean.Address"};		}	}		public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {   		@Override		public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {   			AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();			registry.registerBeanDefinition("com.lzb.other.bean.User",definition);		}	}@Import()注解底层应该有某种方法,使得一执行这个注解,就会将bean加入到容器中

3.自定义@Enable*类型注解

由于@Import()的功能,我们知道只要引入了这个注解就相当于定义了引入的bean,所以我们只需要写一个衍生注解就可以实现功能:
@Retention(RetentionPolicy.RUNTIME)@Target({   ElementType.TYPE})@Documented@Import(User.class)public @interface EnableUser {   }@EnableUser配合getbean或者@Autowired就可以注入

四、@SpringBootApplication

1. @SpringBootApplication启动注解

@SpringBootApplication包括:		@SpringBootConfiguration		@EnableAutoConfiguration		@ComponontScan

2. @SpringBootConfiguration

@Configuration衍生注解,和spring-boot配套使用
@Target({   ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration {       @AliasFor(        annotation = Configuration.class    )    boolean proxyBeanMethods() default true;}

3.@EnableAutoConfiguration

它是通过@Import导入了AutoConfigurationImportSelector.class,这个类是通过父类实现了ImportSelector接口,并重写了selectImports()方法,来实现bean注入
AutoConfigurationImportSelector类有一个getCandidateConfigurations()方法,这个方法就是用来加载META-INF/spring.factories配置文件,返回可以加载的配置类名的字符串集合,这些字符串就是可加载的类名,进入spring.factories可以发现,他加载了许多类名,但并不是所有的类都会被加载,因为每一个类都有一个@ConditionOn*注解,大多数是@ConditionOnClass(*.class)这个注解用来判定是否加载该类。这个文件十分重要,因为只要启动spring-boot项目,这个文件就会被加载并导入可加载的bean
protected List
getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List
configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }

4.@EnableConfigurationProperties(Redis.properties)

原理就是@Enable*,它能够将配置了@ConfigurationProperties(prefix = "redis")的属性文件类导入到容器中,并且优先使用application.yml设置的值

5.自定义starter

这是属性配置类,用来和接收application.yml设置的值,好传递给其它需要的类
package com.lzb.redis.configure;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "redis")public class RedisProperties {       private String host = "localhost";    private int port = 6379;    public String getHost() {           return host;    }    public void setHost(String host) {           this.host = host;    }    public int getPort() {           return port;    }    public void setPort(int port) {           this.port = port;    }}
这是提供bean的类,通过@EnableConfigurationProperties(RedisProperties.class)注入配置文件的值,来实现参数的动态化
package com.lzb.redis.configure;import org.springframework.beans.factory.annotation.Autowired;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;import redis.clients.jedis.Jedis;@EnableConfigurationProperties(RedisProperties.class)@Configuration@ConditionalOnClass(Jedis.class)public class RedisConfiguration {       /**     * 提供jedis的bean     */    @Bean    @ConditionalOnMissingBean(name = "jedis")    public Jedis jedis(RedisProperties redisProperties){           return new Jedis(redisProperties.getHost(),redisProperties.getPort());    }}
这是配置文件resources/META-INF/spring.factories 它是随着@EnableAutoConfiguration启动注解加载的,它会先找到这个类,然后对它进行实例化bean的操作,如果满足@ConditionalOnClass(Jedis.class)和@ConditionalOnMissingBean(name = "jedis"),就会将这个bean加入到容器中,否则不创建这个bean                    ↓
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  com.lzb.redis.configure.RedisConfiguration
上一篇:Maven
下一篇:spring-boot简单入门

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2025年03月19日 20时22分23秒