spring扩展点总结

1  beandiFinition

       1 BeanDeFinitionRegistryPostProcessor的扩展

       2 对ImportBeanDeFinitionRegistrar扩展

       3  对ImportBeanDeFinitionRegistrar扩展

         参考spring扩展点实战第一篇-beandifinition的自定义收集_tyd东的博客-CSDN博客

2 bean

     

         1 InitializingBean

               执行时机:

                 bean ioc之后 执行后置处理器的after方法之前

                 源码:

               

 Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            //这里
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method Failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

                应用场景:

springmvc中就在AbstractHandlerMethodMapping的这个扩展点去加载映射信息,举例:假设你需要将某些信息提前预热到jvm缓存 可以在管理缓存的bean的这个扩展点去做

          2 @postconstruct

             这个会上面提前一点 在before中执行,以spring的习惯是由一个处理器在初始化之前收集了该注解,后面在这里面进行反射调用,具体没去找,不研究这么细了,但是spring的这种思想就是如此,先收集 封装到一些地方 后面再在某个处理器去调用

          3 disposableBean

            执行时机:

           收集是在bean的实例化过程中,执行是在容器销毁的时候 会来销毁bean

             源码:

                

 protected void registerdisposableBeanIfNecessary(String beanName, Object bean, RootBeanDeFinition mbd) {
        AccessControlContext acc = System.getSecurityManager() != null ? this.getAccessControlContext() : null;
        if (!mbd.isPrototype() && this.requiresDestruction(bean, mbd)) {
            if (mbd.isSingleton()) {
                this.registerdisposableBean(beanName, new disposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc));
            } else {
                Scope scope = (Scope)this.scopes.get(mbd.getScope());
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                }

                scope.registerDestructionCallback(beanName, new disposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc));
            }
        }

    }

 这里收集,后面调用 就是spring的一贯思想

应用场景 

         在bean销毁的时候 需要释放资源啥的,可以在这里扩展

4 aware

       执行时机:

           在bean的initializeBean方法

        源码:

              

private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware)bean).setBeanName(beanName);
            }

            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = this.getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }

            if (bean instanceof beanfactoryAware) {
                ((beanfactoryAware)bean).setbeanfactory(this);
            }
        }

    }

和ApplicationContextAwareProcessor里

 应用场景:

暂时没找到 假设需要applicationContext可以直接注入进来,比较鸡肋

 

5  ApplicationListener

    这就是基于一个事件发布订阅

    源码

              

 this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishbeanfactoryInitialization(beanfactory);
                this.finishRefresh();

在refresh方法里 这个initApplicationEventMulticaster就是一个初始化一个事件管理器,后续发布事件和找到对应的监听器都是基于这个类做的,this.registerListeners()就是spring自己和开发定义好的监听器,最后finishrefreh就会发布一个contextRefreshed的事件,

 应用场景:

很多开源框架需要基于spring的各种事件做处理 像nacos里客户端监听WebServerInitializedEvent才像服务器注册

6  @bean和fatoryBean和registerBean()

    适用场景:

     @Bean和fatoryBean都是适用于创建复杂的bean或者这些类不是开发者自己写的,正常的bean都是通过反射

@Bean因为类不是开发者自己开发的类 是由别人开发好的,你只需要创建即可,

fatoryBean是适用开源框架生成一些复杂的类注入到spring.具体类也不由开发者自己创建,在注册成bd的时候 会改变它的beanClass属性变成框架的factorybean(Mapperfactorybean),在实例化的时候 会根据getobject方法生成对应的代理对象

registerBean是自己向容器添加对象,这里面会注册一个bd,在getbean的时候会实例化它,这种用的也很少,因为添加别人开发的类 你用@bean就好了

源码

就不展示了,只知道@bean是改变fatory-method,那么以spring的习惯是在扫描的时候 判断有没有@bean注解 如果有的话 将该方法封装下放到一个地方 并且在注册bd的时候 去改变factory-method和beanname属性,在实例化的时候 调用到factory-method的时候 去调用对应的方法创建对象

fatory-bean: 就是有行代码判断是否实现了factorybean 如果是 就调用getobject方法,这里就不详细展示了

3 springmvc

暂时想到的就是自己添加拦截器,过滤器,转换器啥的 其余的没想到

4 springboot

感觉用的最多的就是自定义starter

适用场景:

自己把bean写好,使用方引入了你的starer,bean会自己注入到spring容器中,不需要别人注入

源码:

spi的思想, 不细讲了  也是提供starer的开发者需要实现这个规范 那么它的类就能被springboot项目扫描到它的类 并变成bean ,因为spirngboot项目扫不到jar包的componetScan注解

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetaDataLoader.loadMetadata(this.beanClassLoader);
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

demo代码:

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <version>0.0.2-SNAPSHOT</version>
    <artifactId>tyd-study-spring-starter</artifactId>
    <groupId>com.tyd.study</groupId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>


    </dependencies>

    定义好meta-inf的spring.factories中加

   

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tyd.spring.starter.MyStarterConfig
package com.tyd.spring.starter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyStarterConfig {

    @Bean
    public MyStarerBean myStarerBean(){
        return new MyStarerBean();
    }
}

在install一下 再引入你的starter包 就能用你这个starer里的bean了

总结

1 spring的思想 总是先收集,收集的数据封装好,后面在某个地方去使用

2 任何类都会变成beandeFinition,这是类的初始化,就像从java文件到class文件必须要编译器,再到class对象必须要类加载器一样,再变成bean,就必须先变成bd,里面是类的定义,实例化只有一个入口那就是getBean(),这样类的生命周期就很清晰明了

3 beanpostProcesser 是一种扩展点思想,都是些接口 再bean的初始化(beanfactoryPostProesser)到实例化 伴随着各种beanPostProdcessor,都是可扩展,可插拔,这也是接口的基本思想,我们在平时的项目在一个主流程不怎么变的调度中 也可以去留一些扩展点

4 spring中使用了lifeCycle 这个也是一种思想

暂时想到是这些,后续想到再补充

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...