本文以spring的配置读取类为例,说明spring boot如何通过spring.factories创建Bean对象。然后讲了springboot-autoconfigure做了什么事情,以及我们的自定义配置类和引入的自动配置发生冲突时如何解决。
-
获得环境变量后处理器的实现类名
在图1.3中可以看到Spring去spring,factories文件中查找实现类。
图1.1执行完毕后,会获取到多个EnviromentPostProcesser的实现类
-
创建环境变量后处理器
在Spring中,EnvironmentPostProcessorApplicationListener在监听到事件后会创建环境变量后处理器。![图2.1](https://i-blog.csdnimg.cn/direct/5c4f3005334b44feab7fd5230bc42948.png -
springBootAutoConfiguration做了什么
在启动spring-boot时,我们通常会用到spring-boot-autoconfigure jar包来帮我们自动引入mvc,jdbc等依赖。
在图3.2中,可以看到spring-boot-autoconfigure jar包下的spring.factories里存放了众多的自动配置类,这些自动配置类最终创建了各个我们需要的Bean对象。 -
配置冲突如何解决
图4.1展示了一个很常见的bean注册失败的错误,
问题的根源在于图4.2中定义了两个一样的Bean,也就是Bean1,并且spring-boot设置了不允许覆盖bean定义。
context.getDefaultListableBeanFactory().setAllowBeanDefinitionOverriding(false);
解决图4.1的问题有两个方法
(1)允许覆盖bean定义
context.getDefaultListableBeanFactory().setAllowBeanDefinitionOverriding(false);
如果允许覆盖bean定义的话,后被加载的bean定义会覆盖前一个。
(2)加上@ConditionalOnMissingBean注解
5. 自动配置AOP
以AOP自动配置类为例,我们看下AOP自动配置类引入了哪些内容。
图5.1中context.registerBean(Config.class)会将类型为Config的bean注册到spring容器中,Config类通过MyImportSelector 引入了 AopAutoConfiguration。
运行main方法,输出为图5.2所示:
图5.2中,注册了Config bean对象后,紧接着注册了4个aop相关的自动配置类。
看一下AopAutoConfiguration内部
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.boot.autoconfigure.aop;
import org.aspectj.weaver.Advice;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"auto"},
havingValue = "true",
matchIfMissing = true
)
public class AopAutoConfiguration {
public AopAutoConfiguration() {
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration() {
}
@Bean
static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
return (beanFactory) -> {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
};
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({Advice.class})
static class AspectJAutoProxyingConfiguration {
AspectJAutoProxyingConfiguration() {
}
@Configuration(
proxyBeanMethods = false
)
@EnableAspectJAutoProxy(
proxyTargetClass = true
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
static class CglibAutoProxyConfiguration {
CglibAutoProxyConfiguration() {
}
}
@Configuration(
proxyBeanMethods = false
)
@EnableAspectJAutoProxy(
proxyTargetClass = false
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "false"
)
static class JdkDynamicAutoProxyConfiguration {
JdkDynamicAutoProxyConfiguration() {
}
}
}
}
类上面的@ConditionalOnProperty注解表明当系统指定spring.aop.auto=true或者没有指定spring.aop.auto时,默认创建AopAutoConfiguration bean对象。
CglibAutoProxyConfiguration和JdkDynamicAutoProxyConfiguration上的@ConditionalOnProperty注解则表示默认情况使用cglib实现aop。