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 这个也是一种思想
暂时想到是这些,后续想到再补充