J2EE-026 Spring容器源码解析(一)构建后置处理器


我们工作中经常用到Spring容器,一谈Spring都知道DI(依赖注入),IOC(控制翻转),但是少人认知Spring容器的体系是如何的

DI和IOC

IOC(控制反转)

控制:什么控制谁控制了谁?
在我们传统的认知中,A调用B一定会声明B,这个时候A就控制了B,这个就是控制。
反转:反转了什么?正转是什么?
正转:A能控制B的生命周期就是正转。
反转:B掌握自己的生命周期就是反转。
在这里插入图片描述

B如何掌握自己的生命周期,万物包一层,我们包一层容器,这个容器控制B的生命周期,称之为IOC(Inversion of Control)
IOC是种编程思想,通常我们创建对象会在类内部进行创建,这个时候我们这个类的生命周期则完全交于使用类,什么时候创建什么时候销毁我们无法控制,对于程序的堆栈管理不够清晰。如图:
在这里插入图片描述
2.DI(依赖注入)
依赖:依赖了什么东西?为什么依赖?
依赖于IOC容器,因为需要将容器里的东西创建进行
注入:注入了什么?为什么注入?
注入A类所需要的资源(类,静态属性之类的),因为外部资源类统一交由IOC容器管理,不由本类控制生命周期。
DI(ependency Injection)是控制反转衍生出来的一种解决方案,通过调用构造函数或者Set方法将方法注入进去。

提出问题

在Spring容器中,我们标注@Service,@Autowird为什么就创建了实例?@Lazy(true)如何实现延迟加载?
其实在之前的ORM脚手架文章的时候已经有一部分答案,这里将探讨Spring中是如何实现的。

源码梳理

AnnotationConfigApplicationContext解析

new AnnotationConfigApplicationContext("org.example.mvc");

进一步
发现调用的this关键字,this就是调用自己的无惨构造函数

public AnnotationConfigApplicationContext(String... basePackages) {
        this();
        this.scan(basePackages);
        this.refresh();
    }

我们查看无参构造函数,发现又传入一个this

  public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

我们再次进入发现this其实是一个BeanDefinitionRegistry接口

public interface BeanDefinitionRegistry extends AliasRegistry

我们Ctrl+H查看一下那些类实现了这个接口
在这里插入图片描述
我们发现AnnotainConfigApplicationContext继承于GenericApplicationContext实现于BeanDefinitionRegistry
当子类构造的时候,父类的构造函数会优先构造,因此我们去看GenericApplicationContext类中的构造函数

    public GenericApplicationContext() {
        this.customClassLoader = false;
        this.refreshed = new AtomicBoolean();
        this.beanFactory = new DefaultListableBeanFactory();
    }

发现这里新建了2个对象DefaultListableBeanFactoryAtomicBoolean

  public DefaultListableBeanFactory() {
        this.autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;
        this.resolvableDependencies = new ConcurrentHashMap(16);
        this.beanDefinitionMap = new ConcurrentHashMap(256);
        this.mergedBeanDefinitionHolders = new ConcurrentHashMap(256);
        this.allBeanNamesByType = new ConcurrentHashMap(64);
        this.singletonBeanNamesByType = new ConcurrentHashMap(64);
        this.beanDefinitionNames = new ArrayList(256);
        this.manualSingletonNames = new LinkedHashSet(16);
        this.configurationFrozen = false;
    }

我们发现这里都是初始化一些默认的自动匹配注入的一些东西,结合名字会可以认定一个初始化IOC容器
AtomicBoolean是函数操作就没有必要截屏上来了

当前的类结构
在这里插入图片描述
我们看完上面后,回看后面AnnotatedBeanDefinitionReader这个对象构建了什么东西

我们走进去后发现这段代码

  AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

这里名字的意思构建注解配置处理器,我们进去后发现它构建了一个工厂把后置处理器构建了进去

 public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }

            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
        RootBeanDefinition def;
        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
            def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
        }
        //代码太多,占篇幅,截取了一部分实例,谢谢
        return beanDefs;
    }

代码太多,占篇幅,截取了一部分实例,谢谢

什么是后置处理器?
后置处理是抽象集中处理方法,不管具体类的核心的集中方法,就好比这样的代码

if(A instanceof  B){
  A.hello();
}

不过他会把注解标记了的Class注入到Set

registerAnnotationConfigProcessors类关键代码:构建工厂

registerAnnotationConfigProcessors方法还有个工厂创建的关键代码

DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);

我们走进去看看,是将registry转为BeanFactory工厂,这里传入的都是实现了BeanDefinitionRegistry接口的方法,这里只有2个类AnnotainConfigApplicationContextGenericApplicationContext

 @Nullable
    private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
        if (registry instanceof DefaultListableBeanFactory) {
            return (DefaultListableBeanFactory)registry;
        } else {
            return registry instanceof GenericApplicationContext ? ((GenericApplicationContext)registry).getDefaultListableBeanFactory() : null;
        }
    }

这里有个getDefaultListableBeanFactory()方法,

   public final DefaultListableBeanFactory getDefaultListableBeanFactory() {
        return this.beanFactory;
    }

这个beanFactory()方法是构建的DefaultListableBeanFactory 构造函数中构建的DefaultListableBeanFactory,拿到这个Factory工厂后把后置器Processor注入进去

registerAnnotationConfigProcessors另一处关键代码,定义我们可以使用的注解代码 Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
BeanDefinition,是个什么?
在这里插入图片描述
继承了特性,作用域,这个BeanDefinitionHolder就是我们的Bean都会转为这个对象

registerAnnotationConfigProcessors类关键代码:判断

registry.containsBeanDefinition的本质就是看工厂是否有这个Bean的存在,因此我们看BeanDefinitionRegistry中的BeanDefinition getBeanDefinition(String var1)方法

我们点击registry.containsBeanDefinition看发现是接口BeanDefinitionRegistry

public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;

    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    boolean containsBeanDefinition(String var1);

    String[] getBeanDefinitionNames();

    int getBeanDefinitionCount();

    boolean isBeanNameInUse(String var1);
}

GenericApplicationContext类实现了BeanDefinitionRegistry接口,前面registry是传入的this,也就是本类,本类没有实现这个方法,因此在继承的抽象方法中找到了,getBeanDefinition方法,本质是抽象类帮忙构建的。

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        return this.beanFactory.getBeanDefinition(beanName);
    }

图解在这里插入图片描述

文章总结

这篇主要讲解了IOC,DI,AnnotationConfigApplicationContext时创建的第一个对象的构建过程,构建后置对象的中工厂的注入和后置处理器的判断,顺带提了一下类会转为BeanDefinitionHolder这个对象注入。需要自己一个一个顺着文章去看一遍就大概明白了。

没有代码。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值