Spring 源码(17)Spring Bean的创建过程(8)Bean的初始化
知识回顾
Bean
的创建过程会经历 getBean
, doGetBean
, createBean
, doCreateBean
,然后 Bean
的创建又会经历实例化,属性填充,初始化。
在实例化 createInstance
时大致可以分为三种方式进行实例化:
-
使用
Supplier
进行实例化,通过BeanFactoryPostProcessor
对BeanDefinition
进行修改,增加一个Supplier
属性,放置一个lambda
表达式用于创建对象 -
使用
factory-method
进行实例化- 使用实例工厂实例化
- 使用静态工厂实例化
-
使用构造器反射进行实例化
SmartInstantiationAwareBeanPostProcessor
在属性填充 populateBean
时大致可以分为4个步骤:
-
调用
InstantiationAwareBeanPostProcessor
接口的after
方法修改Bean
的信息 -
自动装配,将解析的属性和属性值放入到
pvs
变量中autowireByType autowireByName
-
执行通过
CommonAnnotationBeanPostProcessor
和AtowiredAnnotationBeanPostProcessor
解析的注解,然后注入到字段上 -
对属性的值进行解析,解析
pvs
, 会涉及到参数转换,spel
表达式解析,引用类型,String
类型,List
类型,Map
类型,Set
类型,Properties
类型的解析,属性编辑器的解析等。
接下来解读初始化阶段
bean的初始化
bean
的初始化 initializeBean
方法,直接上源码:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 执行Aware 方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 执行 BeanPostProcessor before 接口 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 执行 init-method 方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 执行BeanPostProcessor after 方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
源码逻辑也很简单,大概就分成了4步:
-
执行
Aware
接口的方法invokeAwareMethods
-
执行
BeanPostProcessor#postProcessBeforeInitialization
- 执行初始化方法
-
执行
BeanPostProcessor#postProcessAfterInitialization
执行Aware接口的方法
点进去:
private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) { // 执行BeanNameAware if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } // 执行BeanClassLoaderAware if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } // 执行BeanFactoryAware if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
这里只执行了3个接口的方法, BeanNameAware
, BeanClassLoaderAwre
, BeanFactoryAware
,在 Spring
容器中不止这些 Aware
接口,这里为什么只执行了三个Aware接口?
在 Spring
容器 BeanFactory
构造时,对这三个接口进行了忽略:
public AbstractAutowireCapableBeanFactory() { super(); ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); }
所以这里只执行了这三个 Aware
接口,这里忽略,实际上就是不然这些属性通过自动装配设置属性值,而是通过 Spring
自己的回调进行设置值。
另外我们在开始的准备 BeanFactory
的时候又进行了忽略 Aware
接口:
beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
这6个接口在哪里执行的呢?在 BeanFactory
准备阶段注册了一个 BeanPostProcessor
的实现叫 ApplicationContextAwareProcessor
类,这个类的 before
方法中就进行了调用:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){ return bean; } AccessControlContext acc = null; if (System.getSecurityManager() != null) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { // 执行Aware接口 invokeAwareInterfaces(bean); } return bean; } 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); } }
为什么要分开处理呢?
个人认为主要是做了个区分而已,前面三个接口输入 BeanFactory
范畴,而这6个接口属于 ApplicationContext
范畴,只是进行了归类处理而已。
执行BPP的Before方法
代码比较简单,就是循环的执行了 BPP
的 before
接口,这里在执行的时候,实现上也执行了在 Bean
进行 merge
的时候解析的 @PostConstruct
注解。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { // 执行初始化方法 metadata.invokeInitMethods(bean, beanName); } catch (InvocationTargetException ex) { throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Failed to invoke init method", ex); } return bean; }
这个方法的实现类为 InitDestroyAnnotationBeanPostProcessor
执行初始化方法
执行初始化方法的时候,会分为两步,一个是执行 InitializingBean
的 afterPropertiesSet
方法,另一个是执行自定义的 init-method
方法
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { // 判断当前Bean是否是实现了InitializingBean boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { // 执行 ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { // 执行自定义的初始化方法 invokeCustomInitMethod(beanName, bean, mbd); } } }
执行BPP的after接口
BPP的after主要是用来实现AOP的,所以这里简单介绍下,循环执行after方法的调用。
源码:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
源码比较简单,就循环执行了方法的调用。
初始化就解读完了, Spring
的 Bean
的创建也基本讲完,最终创建出来的 Bean
对象就会放入到一级缓存 singletonObjects
中。
- Flex & Bison 开始
- Obsidian基础教程
- 分享自己平时使用的socket多客户端通信的代码技术点和软件使用
- iNeuOS工业互联网操作系统,增加2154个视图建模(WEB组态)行业矢量图元、大屏背景及相关图元
- 多台云服务器的 Kubernetes 集群搭建
- Elasticsearch学习系列四(聚合搜索)
- 关于swiper插件在vue2的使用
- 使用 Abp.Zero 搭建第三方登录模块(一):原理篇
- LVGL库入门教程 - 颜色和图像
- Node.js精进(4)——事件触发器
- 物联网?快来看 Arduino 上云啦
- SpringBoot JWT Redis 开源知识社区系统
- CVPR2022 | 可精简域适应
- Spring框架系列(3) - 深入浅出Spring核心之控制反转(IOC)
- 面试突击59:一个表中可以有多个自增列吗?
- CVPR2022 | 弱监督多标签分类中的损失问题
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的...
- Spring Security:用户和Spring应用之间的安全屏障
- Mybatisi和Spring整合源码分析
- 前端学习 linux —— 第一篇