spring扩展点总结

Spring Framework

遇事不决上面找

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);
            }
        }

    }

        应用场景:

         暂时没找到 假设需要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

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

继承WebMvcConfigurationSupport

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代码: 

pom中只需要引入一个boot-starter

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>tyd-study</artifactId>
        <groupId>com.tyd.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <version>0.0.5-SNAPSHOT</version>
    <artifactId>tyd-study-spring-starter</artifactId>
    <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-starter</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>


    </dependencies>



</project>

    定义好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了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值