1.启动接口介绍
具体的流程图:
Spring扫描底层流程 | ProcessOn免费在线作图,在线流程图,在线思维导图 |
-
AnnotationConfigApplicationContext接口主要做了两件事情:1.scan 2.加载非懒加载的spring a.对象68和70行是java中的JFR机制,相当于查看69行代码执行的黑盒子(耗时,性能等)
b.ClassPathBeanDefinitionScanner接口主要是把扫描到的BeanDefinition注册到spring容器中
c.当有两个类通过component注解的时候,如果内容一致,那么是不会报错的,isCompatible->中newDefinition.getSource().equals(existingDefinition.getSource())会判断资源是不是一致,如果一致直接返回false,这样checkCandidate接口就不会添加新的bean
if (this.checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
this.registerBeanDefinition(definitionHolder, this.registry);
}
d.可以在resources添加spring.components
其中文件内容:com.zhouyu.service.UserService=org.springframeweork.stereotype.Colmponent
e.加载非懒加载的spring
this.refresh()->this.finishBeanFactoryInitialization(beanFactory)->beanFactory.preInstantiateSingletons()
f.SmartInitializingSingleton是在所有的非懒加载的单例Bean创建完成之后执行的代码
g.这样在getBean的时候会调用有参的构造函数,但是因为UserService是一个单例对象,在new AnnotationConfigApplicationConfig的时候就创建了,所以此处还是打印了0.
@Component
public class UserService {
private OrderService orderService;
public UserService() {
System.out.println(0);
}
public UserService(OrderService orderService) {
System.out.println(1);
this.orderService = orderService;
}
public void test() {
System.out.println("test");
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService", new OrderService());
userService.test();
}
}
2.实例化前
当前BeanDefinition对应的类成功加载后,就可以实例化对象了,但是…
在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。这个扩展点叫
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
。比如:
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
}
return null;
}
}
如上代码会导致,在userService这个Bean实例化前,会进行打印。
值得注意的是,postProcessBeforeInstantiation()是有返回值的,如果这么实现:
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
return new UserService();
}
return null;
}
}
userService这个Bean,在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。具体的代码细节在:createBean->resolveBeforeInstantiation中
3.实例化
在这个步骤中就会根据BeanDefinition去创建一个对象了。
3.1 实例化后,属性初始化之前可以使用MergedBeanDefinitionPostProcessor接口,进行一些初始化的操作,可以调用初始化接口、属性填充···
【eg】
扩展:对于任何一个Bean的执行流程如下:
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- 实例化
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- getResolvedAutowireMode属性赋值(spring自带的依赖注入)
- InstantiationAwareBeanPostProcessor.postProcessProperties()(解析spring自带的autowired)
- Aware对象
- BeanPostProcessor.postProcessBeforeInitialization(),(包括@PostConstruct方法)
- 初始化
- BeanPostProcessor.postProcessAfterInitialization()
- beans.xml中<context:annotation-config/>就是将AutowiredAnnotationBeanPostProcessor作为一个bean加入到了spring容器中,然后对所有的注解@Autowired进行解析
4.Bean的销毁过程(销毁只涉及单例,原型的不涉及销毁,因为每次都是使用的时候再创建,并且没有任何保存操作)
Bean的销毁过程是在spring容器的关闭过程中的。比如:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();
在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean:
- 当前Bean是否实现了DisposableBean接口
- 或者,当前Bean是否实现了AutoCloseable接口
- BeanDefinition中是否指定了destroyMethod
- 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
-
- ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
- InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean
- 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)
在Spring容器关闭过程时:
- 首先发布ContextClosedEvent事件
- 调用lifecycleProcessor的onCloese()方法
- 销毁单例Bean
-
- 遍历disposableBeans
-
-
- 把每个disposableBean从单例池中移除
- 调用disposableBean的destroy()
- 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
-
如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉 (inner bean参考
Core Technologies
)
-
-
- 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName
- 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组
- 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean
这里涉及到一个设计模式:
适配器模式
在销毁时,Spring会找出实现了DisposableBean接口的Bean。
但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属于“DisposableBean”,这些Bean在容器关闭时都要调用相应的销毁方法。
所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter。
会把实现了AutoCloseable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter实现了DisposableBean接口。