属性填充
功能:对bean中需要自动装配的属性进行填充
角色:
1、AutowiredAnnotationBeanPostProcessor
2、CommonAnnotationBeanPostProcessor
在上一个流程中,我们已经找到了所有需要自动装配的Member
,所以这一部流程就显得非常简单了
我们同样以AutowiredAnnotationBeanPostProcessor
为例
1、使用beanName为key,从缓存中取出InjectionMetadata
2、遍历InjectionMetadata
中的checkedElements
集合
3、取出Element
中的Member
,根据Member
的类型在Spring中获取Bean
4、使用反射将获取到的Bean设值到属性中
推导过程
在Spring中,Bean填充属性之后还可以做一些初始化的逻辑,比如Spring的线程池ThreadPoolTaskExecutor
在填充属性之后的创建线程池逻辑,RedisTemplate
的设置默认值。
Spring的初始化逻辑共分为4个部分:
1、invokeAwareMethods:调用实现特定Aware
接口的方法
2、applyBeanPostProcessorsBeforeInitialization:初始化前的处理
3、invokeInitMethods:调用初始化方法
4、applyBeanPostProcessorsAfterInitialization:初始化后的处理
invokeAwareMethods
这块逻辑非常简单,我直接把源码粘出来给大家看看就明白了
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 = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
初始化前的处理
功能:调用初始化方法前的一些操作
角色:
1、InitDestroyAnnotationBeanPostProcessor:处理@PostContrust注解
2、ApplicationContextAwareProcessor:处理一系列Aware接口的回调方法
这一步骤的功能没有太大的关联性,完全按照使用者自己的意愿决定想在初始化方法前做些什么,我们一个一个来过
1.InitDestroyAnnotationBeanPostProcessor
这里的逻辑与属性填充过程非常相似,属性填充过程是取出自动装配
相关的InjectionMetadata
进行处理,而这一步则是取@PostContrust
相关的Metadata
进行处理,这个Metadata
同样也是在处理BeanDefinition过程解析缓存的
1、取出处理BeanDefinition过程解析的LifecycleMetadata
2、遍历LifecycleMetadata
中的checkedInitMethods
集合
3、使用反射进行调用
2.ApplicationContextAwareProcessor
这一步与invokeAwareMethods大同小异,只不过是其他的一些Aware接口,同样直接粘上代码
private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } }
初始化方法
在Spring中的初始化方法有两种
1、实现InitializingBean
接口的afterPropertiesSet
方法
2、@Bean
注解中的initMethod
属性
调用顺序是先调用afterPropertiesSet
再initMethod
1、判断Bean是否实现InitializingBean
接口
2、是则将Bean强转成InitializingBean
,调用afterPropertiesSet
方法
3、判断BeanDefinition中是否有initMethod
4、是则找到对应的initMethod
,通过反射进行调用
初始化后的处理
在Spring的内置的后置处理器中,该步骤只有ApplicationListenerDetector
有相应处理逻辑:将实现了ApplicationListener接口的bean添加到事件监听器列表中
如果使用了Aop相关功能,则会使用到
AbstractAutoProxyCreator
,进行创建代理对象。
ApplicationListenerDetector
的流程如下
1、判断Bean是否是个ApplicationListener
2、是则将bean存放到applicationContext
的监听器列表中
补充流程图
到这里,Bean的生命周期主要部分已经介绍完了,我们将流程图补充一下
同样还有其他的一些逻辑
1、中止创建Bean的过程
该过程处于Bean生命周期的最开始部分。
功能:由后置处理器返回Bean,达到中止创建Bean的效果
角色:无,Spring的内置后置处理器中,无实现。
Bean的生命周期十分复杂,Spring允许你直接拦截,即在创建Bean之前由自定义的后置处理器直接返回一个Bean给Spring,那么Spring就会使用你给的Bean,不会再走Bean生命周期流程。
案例演示:
@Component public class Car { @Autowired private Person person; public void checkPerson(){ if(person == null){ System.out.println("person is null"); } } }
由于在Person
属性上加了@Autowired
,所以正常来说person必然不能为空,因为这是必须要注入的。
现在我们自定义一个BeanPostProcessor进行拦截
@Component public class InterruptBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if("car".equals(beanName)){ try { return beanClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } return null; } }
测试结果如下
2、提前缓存刚实例化的对象
该步骤跟随在Spring实例化bean之后,将bean进行缓存,其目的是为了解决循环依赖问题。
该过程暂时按下不表,单独提出放于循环依赖章节。
3、中止填充属性操作
与中止创建Bean逻辑相同,Spring同样也允许你在属性填充前进行拦截。在Spring的内置处理器中同样无该实现。
实现手段为实现InstantiationAwareBeanPostProcessor
接口,在postProcessAfterInstantiation
方法中返回false
@Component public class InterruptBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if(beanName.equals("car")){ return false; } return true; } }
4、注册Bean的销毁方法
Spring中不仅有@PostContrust
、afterProperties
、initMethod
这些bean创建时的初始化方法,同样也有bean销毁时的@PreDestory
、destroy
,destroyMethod
。
所以在Bean的生命周期最后一步,Spring会将具备这些销毁方法的Bean注册到销毁集合中,用于系统关闭时进行回调。
比如线程池的关闭,连接池的关闭,注册中心的取消注册,都是通过它来实现的。
完整流程图
最后,附上一张Bean生命周期的完整流程图