springFactories原理

本文以spring的配置读取类为例,说明spring boot如何通过spring.factories创建Bean对象。然后讲了springboot-autoconfigure做了什么事情,以及我们的自定义配置类和引入的自动配置发生冲突时如何解决。

  1. 获得环境变量后处理器的实现类名
    图1.1 获得环境变量后处理器的实现类名
    图1.2
    图1.3
    在图1.3中可以看到Spring去spring,factories文件中查找实现类。
    图1.1执行完毕后,会获取到多个EnviromentPostProcesser的实现类
    图1.4

  2. 创建环境变量后处理器
    在Spring中,EnvironmentPostProcessorApplicationListener在监听到事件后会创建环境变量后处理器。![图2.1](https://i-blog.csdnimg.cn/direct/5c4f3005334b44feab7fd5230bc42948.png在这里插入图片描述

  3. springBootAutoConfiguration做了什么
    在启动spring-boot时,我们通常会用到spring-boot-autoconfigure jar包来帮我们自动引入mvc,jdbc等依赖。
    图3.1
    图 3.2
    在图3.2中,可以看到spring-boot-autoconfigure jar包下的spring.factories里存放了众多的自动配置类,这些自动配置类最终创建了各个我们需要的Bean对象。

  4. 配置冲突如何解决
    图 4.1
    图4.1展示了一个很常见的bean注册失败的错误,图4.2
    问题的根源在于图4.2中定义了两个一样的Bean,也就是Bean1,并且spring-boot设置了不允许覆盖bean定义。

context.getDefaultListableBeanFactory().setAllowBeanDefinitionOverriding(false);

解决图4.1的问题有两个方法
(1)允许覆盖bean定义

context.getDefaultListableBeanFactory().setAllowBeanDefinitionOverriding(false);

如果允许覆盖bean定义的话,后被加载的bean定义会覆盖前一个。
(2)加上@ConditionalOnMissingBean注解
图 4.3
5. 自动配置AOP
以AOP自动配置类为例,我们看下AOP自动配置类引入了哪些内容。
图 5.1
图5.1中context.registerBean(Config.class)会将类型为Config的bean注册到spring容器中,Config类通过MyImportSelector 引入了 AopAutoConfiguration。
运行main方法,输出为图5.2所示:
图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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值